Skip to content
This repository has been archived by the owner on Nov 24, 2020. It is now read-only.

How can I creat a client with our API Key and Username/Password of a user #1

Closed
DanCooper opened this issue Jun 18, 2016 · 13 comments
Closed

Comments

@DanCooper
Copy link

Hi
sorry, don't found a forum or something other to post my question.

We use our own API to get and set informations to and from Trakt.tv. But we have added only some basic requests and our plan is to switch to your wrapper.

We have a API key for our app (vb.NET), but I don't understand how I can create a client with our API key and username/password that the user fills in settings. Do you can help me with this?

@henrikfroehling
Copy link
Owner

henrikfroehling commented Jun 18, 2016

Hello,
do I understand you correctly, that your API key is your Trakt access token?

Currently there is no way to set the access token as string directly, because I didn't think of this scenario.

A workaround could be to create a TraktClient, set your client id and client secret and then create a new TraktAccessToken instance and save it in the TraktAuthentication module.

Example:

var client = new TraktClient("your application client id", "your application client secret");
var accessToken = new TraktAccessToken { AccessToken = "your access token", ExpiresInSeconds = 7776000 };
client.Authentication.AccessToken = accessToken;

You have to repeat this on every instantiation of the client. Therefore I recommend to serialize the accessToken.

Important to note, is, that you need to set the ExpiresInSeconds property (in this example set to expire after three month) of the TraktAccessToken, because otherwise the token will be invalid and therefore won't work. This will ensure, that the accessToken instance is valid inside the library, but I can't guarantee, that Trakt will accept the access token.

Further note:
As the documentation for the PIN authentication was removed from the official Trakt API documentation, I decided not to implement this functionality.
This library only supports features, which are officially documented by Trakt. In case of authentication, it would be OAuth and Device authentication.

An username and password are not required, if you have an access token, because the user will be identified by the access token.

Maybe I will implement PIN authentication, but I'm not sure about this, because it is deprecated.

If your intention is to set the access token manually, I will see how to fix this.

I hope I could help you.

henrikfroehling added a commit that referenced this issue Jun 24, 2016
@henrikfroehling
Copy link
Owner

You can now set the access token directly in the client.

Example:

var client = new TraktClient("your application client id") { AccessToken = "your access token" };

or

var client = new TraktClient("your application client id");
client.AccessToken = "your access token";

@DanCooper
Copy link
Author

Sound good.
But now I'm a little bit confused:

  • "your application client id" is the API key that i can create for our own software
  • "client.AccessToken" is the token, that will be created after first "login" and will be valid for 3 months

But how i can set the username and passwort of an user to get a new token?
We use that to login the user with his own username and password to get the token: Link
Also we add our API key to header for all requests: Link

Atm we don't need a pin or application permission that has to be confirmed by user.

Sorry, my english is not the best, I hope you understand me :-)
Feel free to contact me over support@embermediamanager.org if you speak german. We can talk about your wrapper via Skype if you want.

@henrikfroehling
Copy link
Owner

henrikfroehling commented Jun 24, 2016

Okay, I think, I misunderstood you a little. :-)

"your application client id" is the API key that i can create for our own software

Yes, it's the Client ID, that you get, when you create your application on Trakt.tv.

"client.AccessToken" is the token, that will be created after first "login" and will be valid for 3 months

Yes, if you mean by "login" the authentication for your application by the user.


Either you already have an access token, then you're good to go and just use it by setting it via

client.AccessToken = "access token";

Or you don't have an access token. Then you must authenticate your application to get an access token.


TraktApiSharp distinguishes between requests, that require authorization with an access token, and requests, that don't require authorization. Just like the Trakt API.

If you only need requests, that don't require authorization (e.g. retrieving data about movies and shows), then you only have to provide your application client id to the library.

var client = new TraktClient("client id");

If you also need requests, that require authorization (e.g. retrieving information about users, checkins, syncs or post requests), then you also have to provide your access token to the library.

var client = new TraktClient("client id") { AccessToken = "your access token" };

If you don't have an access token, then you have two options: OAuth authentication and Device authentication.
There is a third option, PIN authentication. But since it's deprecated, I decided not to implement it, as I already mentioned in my first comment.

The application client secret, that you also get, when you create your application on Trakt.tv, is only needed for the authentication process.


So, to make authentication possible, to get an access token, you have to provide your client id and client secret to the library.

var client = new TraktClient("your client id", "your client secret");

With OAuth authentication you have to follow these steps to get an access token:

  1. Create authorization url: var url = client.OAuth.CreateAuthorizationUrl();
  2. Your application user has to open the returned url
  3. Your application user signs in into Trakt, if necessary, or creates a new account, and then authorizes your application
  4. Your user gets a pin code, which you will need for the next step. Either you parse the response url for the code or you ask your user for the code. We'll assume, the code is 12345678.
  5. var code = "12345678";
  6. Get access token: var traktAuthorization = client.OAuth.GetAuthorizationAsync(code); var accessToken = traktAuthorization.AccessToken;
  7. Save the returned accessToken for later usage or serialize the whole traktAuthorization. The returned traktAuthorization also contains a refresh token (traktAuthorization.RefreshToken), which you have to use to get a new access token, if the three month are expired. It is also automatically saved in the library, but only during runtime. So make sure, to serialize it. ;-)

With Device authentication you have to follow these steps to get an access token:

  1. Generate new device: var device = client.DeviceAuth.GenerateDeviceAsync();
  2. The returned device contains an user code (device.UserCode) and a verification url (device.VerificationUrl), which you have to provide to your application user. The user has to open the verification url and to enter the user code on that website.
  3. Poll for an access token: var traktAuthorization = client.DeviceAuth.PollForAuthorizationAsync(); var accessToken = traktAuthorization.AccessToken;
  4. Same as step 7 in OAuth authentication process.

The TraktAuthorization object contains the access token (TraktAuthorization.AccessToken), refresh token (TraktAuthorization.RefreshToken), the datetime, when it was created (TraktAuthorization.Created) and the seconds, after which it will expire (TraktAuthorization.ExpiresInSeconds).

You can set or get an instance of it via

client.Authorization = new TraktAuthorization();

TraktApiSharp doesn't need the username or password, neither for authentication nor otherwise.

Only the

  • client id for requests without authorization,
  • or client id and access token for requests with authorization,
  • or client id and client secret for the authentication process to get an access token

If you're using this library, you don't have to deal with request headers anymore. It's already implemented in the library. ;-)
See Client ID-, API Version- and Accept Header, and Access Token-Header.


I also added three properties to the client for checking validity.

var client = new TraktClient("client id", "client secret") { AccessToken = "access token" };

bool valid = client.IsValidForUseWithoutAuthorization; // true, when at least client id is given
bool valid = client.IsValidForUseWithAuthorization; // true, when at least client id and access token are given
bool valid = client.IsValidForAuthenticationProcess; // true, when at least client id and client secret are given

A proper documentation for using this library is already on my todo list. ;-)

@ludwich
Copy link

ludwich commented Aug 20, 2016

im trying the same but i cant get your sample code to work since i get errors on accesstoken and usercode and verificationurl. Am i missing a using statement ?

@henrikfroehling
Copy link
Owner

@ludwich What kind of errors / exceptions do you get?

@ludwich
Copy link

ludwich commented Aug 20, 2016

i cant get the var accessToken = traktAuthorization.AccessToken; to work since i get red lined on AccessToken and the same on device.VerificationUrl and device.UserCode.

installed from github first but tested with nuget too now and it cant find the defenition

@henrikfroehling
Copy link
Owner

@ludwich Which version do you use? There was a bug with device authentication in version 0.1.0, that got fixed in version 0.1.1

Did you check the returned TraktDevice, if it is null?

// 1.
TraktClient client = new TraktClient("Your Trakt Client Id", "Your Trakt Client Secret");

// 2.
TraktDevice device = await client.DeviceAuth.GenerateDeviceAsync();

// If successful, otherwise an TraktException was thrown
string userCode = device.UserCode;
string verificationUrl = device.VerificationUrl;

// 3.
TraktAuthorization authorization = await client.DeviceAuth.PollForAuthorizationAsync();

// 4.
// Open a webpage with the verificationUrl, where the user has to sign in / sign up and to enter the userCode
// Polling takes some time, up to device.ExpiresInSeconds seconds.
// It depends on, if and when the user accepts the authentication.
// The library polls and checks every device.IntervalInSeconds seconds, if the authentication was successful

To get any Trakt exceptions, wrap all TraktClient calls in a try/catch-block, like this:

try
{
    ... await client.DeviceAuth....
    ...
}
catch (TraktException ex)
{
    string message = ex.Message;
    HttpStatusCode code = ex.StatusCode;
    string requestUrl = ex.RequestUrl;
    string requestBody = ex.RequestBody;
    string response = ex.Response;
    string reasonPhrase = ex.ServerReasonPhrase;
}

@henrikfroehling
Copy link
Owner

@ludwich

installed from github first but tested with nuget too now and it cant find the defenition

Which defnition specifically?

The only dependency is Newtonsoft.Json, but that should be installed automatically, if you use NuGet.
Internally, the library uses System.Net.Http for HttpClient requests.

@ludwich
Copy link

ludwich commented Aug 20, 2016

Sorry im really new to c# .. I have newtonsoft for json in other programs so i have that but now i get async errors from await call. I cant call it from main ? is there a better place to discuss ?

@henrikfroehling
Copy link
Owner

Yeah, async / await can be tricky, if you're new to it.

The library basically just returns Task objects, which are awaitable and therefore can be executed in a different thread.

For example:

// 1.
Task<TraktDevice> deviceTask = client.DeviceAuth.GenerateDeviceAsync(); // just returns
// vs.
// 2.
TraktDevice device = await client.DeviceAuth.GenerateDeviceAsync(); // executes on a different thread and returns the actual result

Nr. 2 returns the actual result (in this case, the TraktDevice), and the call to client.DeviceAuth.GenerateAsync() was executed on a different thread.

Nr. 1 returns a Task object, which can contain the TraktDevice. The difference to Nr. 2 is, that the Task object has to be executed, like this:

// executes the Task, that was returned from GenerateDeviceAsync(), on a different thread
TraktDevice device = await deviceTask;

to get the actual TraktDevice.

To use await in a method, the method itself must be marked with async, like this:

async void Foo()
{
  var something = await MethodAsync();
}

// instead of this

void Foo()
{
  var something = await MethodAsync();
}

But unfortunately, this is not allowed in your case with the Main method in a (I guess) console program.

There are two good blogposts about async / await:
Async and Await
Async Console Programs

@ludwich
Copy link

ludwich commented Aug 20, 2016

ok. Well atleast this moves me forward =) Ill try again tonight with building functions instead in a console program as you guessed correctly. Thanks for your hardwork and nice support man. Have a great weekend.

@henrikfroehling
Copy link
Owner

I'm glad, I could help.
Thanks, have a great weekend, too.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants