Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authenticating a user with Instagram on iOS: specifying redirect_uri

I am developing an iOS app (using Swift) that allows the user to authenticate through Instagram using OAuth 2.0

In the past, everything was working fine as I was able to specify the authorization URL as such: https://api.instagram.com/oauth/authorize/?client_id=xxx&redirect_uri=myiosapp://authorize&response_type=code

The key point here being the redirect_uri myiosapp://authorize

My problem is that I am no longer able to register a custom url scheme with Instagram thereby making it impossible(?) to handle the redirect exclusively through my app. If I do try to add such a URI in the "Valid redirect URIs:" field, I get the following error:

You must enter an absolute URI that starts with http:// or https://

What is the recommended way to handle authentication with Instagram exclusively thrugh an iOS native application?

like image 387
Matt Pinkston Avatar asked Aug 16 '16 04:08

Matt Pinkston


1 Answers

After figuring it out, I thought I'd post my solution for anyone who comes across the same problem.

First of all, I'll just accept that Instagram no longer allows custom schemas in the "Security" -> "Valid redirect URIs" field. Instead, I will enter an arbitrary but valid URI that I can uniquely identify. For example: http://www.mywebsite.com/instagram_auth_ios

Now, when attempting to authorize with Instagram, I'll use that as the redirect URI - even though no webpage actually exists at that URI. Example: https://api.instagram.com/oauth/authorize/?client_id=xxx&redirect_uri=http://www.mywebsite.com/instagram_auth_ios&response_type=code

Finally, I'll use the UIWebViewDelegate's shouldStartLoadWithRequest method to intercept the redirect request before it runs, and instead call my original custom uri (that way I don't have to rewrite anything). Here's how I wrote that method:

func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
    guard let url = request.URL where url.host == "www.mywebsite.com" && url.path == "/instagram_auth_ios" else { return true }
    guard let authUrl = NSURLComponents(URL: url, resolvingAgainstBaseURL: false) else { return true }

    // Customize the scheme/host/path, etc. as desired for your app
    authUrl.scheme = "myappschema"
    authUrl.host = "instagram"
    authUrl.path = ""
    UIApplication.sharedApplication().openURL(authUrl.URL!)

    return false
}

There's one small caveat with returning false in the shouldStartLoadWithRequest method in that it will always complain with a "Frame Load Interrupted" error. This doesn't seem to adversely affect anything and can (probably) be safely ignored.

like image 184
Matt Pinkston Avatar answered Nov 15 '22 15:11

Matt Pinkston