4

I'm trying to use the Trakt API to get a list of TV shows and other data. However, I'm stuck on authenticating my app with Trakt. I have my API key, secret, and redirect URI, but am struggling on how to authorise my app. I've tried the following:

Method 1, using the sample code from Trakt:

-(void)authorisation{

    NSString *redirectURI = @"http://myappredirect://";
    NSString *clientID = @"MY_CLIENT_ID";
    NSString *clientSecret = @"MY_CLIENT_SECRET";
    NSString *username = @"USERNAME";
    NSString *authURL = [NSString stringWithFormat:@"https://trakt.tv/oauth/authorize?response_type=code&client_id=%@&redirect_uri=%@&state=state&username=%@", clientID, redirectURI, username];

    NSURL *URL = [NSURL URLWithString:authURL];

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
    [request setHTTPMethod:@"GET"];

    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];

    [[UIApplication sharedApplication] openURL:URL];

    NSURLSession *session = [NSURLSession sharedSession];
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request
                                            completionHandler:
                                  ^(NSData *data, NSURLResponse *response, NSError *error) {

                                      if (error) {
                                          // Handle error...
                                          return;
                                      }

                                      if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
                                          NSLog(@"Response HTTP Status code: %ld\n", (long)[(NSHTTPURLResponse *)response statusCode]);
                                          NSLog(@"Response HTTP Headers:\n%@\n", [(NSHTTPURLResponse *)response allHeaderFields]);
                                      }

                                      NSString* body = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                                      NSLog(@"Response Body:\n%@\n", body);
                                  }];
    [task resume];
}

This opens Safari on my iPhone, loads the web page successfully with Trakt asking to authorise my account for my app. I tap 'Authorize' and then Safari loads a URL 'myappredirect//?code=a_really_long_string_of_characters", but with an error

Safari cannot open the page because the server cannot be found.

When I enter myappredirect:// in Safari, my app opens, so I'm wondering if the URL that Safari loads is incorrect as it's missing a semi-colon before the double //?

So I tried adding a UIWebView to my app and load the URL in there. It loads the URL but this time after I tap 'Authorize', it doesn't change the webpage. The UIWebView delegate webViewDidStartLoad does tell me that it loads a page after I tap 'Authorize', but nothing changes on-screen.

Method 2, using OAuth2Client:

-(void)setupWebview{

    webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 300)];
    webView.backgroundColor = [UIColor greenColor];
    webView.delegate = self;
    [self.view addSubview:webView];

}

-(void)webViewDidStartLoad:(UIWebView *)webView{
    NSLog(@"webViewDidStartLoad");
}

-(void)secondMethod{
    NSString *redirectURI = @"http://myappredirect://";
    NSString *clientID = @"MY_CLIENT_ID";
    NSString *clientSecret = @"MY_CLIENT_SECRET";
    NSString *username = @"USERNAME";
    NSString *authURL = [NSString stringWithFormat:@"https://api-v2launch.trakt.tv/oauth/authorize?response_type=code&client_id=%@&redirect_uri=%@&state=state&username=%@", clientID, redirectURI, username];
    NSString *tokenURL = @"https://api-v2launch.trakt.tv";

    [[NXOAuth2AccountStore sharedStore] setClientID:clientID
                                             secret:clientSecret
                                   authorizationURL:[NSURL URLWithString:authURL]
                                           tokenURL:[NSURL URLWithString:tokenURL]
                                        redirectURL:[NSURL URLWithString:redirectURI]
                                     forAccountType:@"Trakt"];

    [[NXOAuth2AccountStore sharedStore] requestAccessToAccountWithType:@"Trakt"
                                   withPreparedAuthorizationURLHandler:^(NSURL *preparedURL){
                                       // Open a web view or similar
                                       [webView loadRequest:[NSURLRequest requestWithURL:preparedURL]];
                                   }];
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:YES];

    [[NSNotificationCenter defaultCenter] addObserverForName:NXOAuth2AccountStoreAccountsDidChangeNotification
                                                      object:[NXOAuth2AccountStore sharedStore]
                                                       queue:nil
                                                  usingBlock:^(NSNotification *aNotification){
                                                      // Update your UI
                                                      NSLog(@"Success");
                                                  }];

    [[NSNotificationCenter defaultCenter] addObserverForName:NXOAuth2AccountStoreDidFailToRequestAccessNotification
                                                      object:[NXOAuth2AccountStore sharedStore]
                                                       queue:nil
                                                  usingBlock:^(NSNotification *aNotification){
                                                      NSError *error = [aNotification.userInfo objectForKey:NXOAuth2AccountStoreErrorKey];
                                                      // Do something with the error
                                                      NSLog(@"Error");
                                                  }];
}

Here, I'm not sure what the token URL is. Again, my UIWebView loads the URL perfectly but after I press 'Authorize', it doesn't change its webpage. The delegate method webViewDidStartLoad does tell me that it loads another page, but nothing changes on-screen. Also, neither of the NXOAuth2 notifications are sent.

I'm new to OAuth2 and would really appreciate any help anybody may have to offer. I apologise if this is a silly question, I'm really struggling on what to do, and confused as to why Safari won't open my app after I've authorised Trakt.

Thanks.

2
  • How to get the parameter authorization code from redirect url. Because after authorization it goes to redirect URL and its not return back to my app. please suggest me Commented May 2, 2016 at 13:10
  • UIWebView . and WebView is not supported for Redirect_url Commented Mar 21, 2018 at 11:40

3 Answers 3

3
NSString *redirectURI = @"myappredirect://";

instead of

NSString *redirectURI = @"http://myappredirect://";
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your answer. I tried this and the Trakt page loads but says 'OAuth Error, the redirect uri included is not valid'. On the Trakt API page on my desktop, I can set the URI but I cannot enter it without 'http://'. So I think http:// is necessary?
If API requires http:// to be URL scheme used in redirect uri, then it is not possible to be redirected from safari back to your app. Every app can be registered to open some URL schemes - for http:// its Safari.
That's strange, every time I try to enter it without http:// on Trakt it says 'Must be an absolute uri.'. How would I handle the user tapping 'Authorize'?
It would seem, that Trakt API does not support authorization in mobile app via external browser. However, OAuth2Client you are using has other options of authorizing user. If i were you, I would take closer look at those
I'm not sure which method to use, I tried the requestAccessToAccountWithType:@"Trakt" withPreparedAuthorizationURLHandler: but that opens it up in a UIWebView, and then I don't know how to handle the response. I also tried the method with username:password: but that also does not work. :S
2

With the UIWebView you have interrupt the load in UIWebView delegate shouldStartLoadWithRequest when the url starts with your redirect url and get the parameter authorization code from url, concatenate with "get token url" and call [[NXOAuth2AccountStore sharedStore] handleRedirectURL:getTokenURL];

May not be the best way, but it works for me. :)

English isn’t my first language, so please excuse any mistakes. I hope this can help you.

2 Comments

I ended up making my own version of NXOAuth2 and this was part of the solution. I forgot to close this question but since you've answered it with the solution, I've marked it as the solution. Thanks!
@Murilo Alborghette How to get the parameter authorization code from redirect url. Because after authorization it goes to redirect URL and its not return back to my app. please suggest me
2

Here's how I did it.

Step 1: Edit your Info.plist

You need to define a url scheme that will open your app instead of the browser, which is useful for the redirect at the end of the oauth process.

Let's call it yoururlscheme for the example, but you can pick whatever you want (eg: "yourappname" in lowercase, or even your bundle identifier "com.example.yourappname")

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>yoururlscheme</string>
        </array>
    </dict>
</array>

Step 2: on trakt.tv

Step 3: your ViewController

import SafariServices

class YourViewController: UIViewController {

  var oauthSession: SFAuthenticationSession? = nil

  func signIn() {
    let clientId = "" // your client id
    let redirectUri = "yoururlscheme://oauth/token"
    let oauthURL = "https://trakt.tv/oauth/authorize?response_type=code&client_id=\(clientId)&redirect_uri=\(redirectUri)"
    oauthSession = SFAuthenticationSession(url: oauthURL, callbackURLScheme: redirectUri) { (url, error) in
        guard let url = url,
            let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false),
            let queryItems = urlComponents.queryItems,
            let code = queryItems.first(where: {$0.name == "code"})?.value else {
            return
        }
        // Do whatever you want with the token now
        print("code: \(code)")
    }
    oauthSession?.start()
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.