Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OAuth2, Swift 3, Instagram

There seem to be lots of changes at IG. Many OAuth2 repos, all seem to have bugs, or really not easily converted to Swift3. Wondering if anyone has a solution for moving to Swift3 and working with the latest changes at Instagram?

Solutions most welcome. OAuth2 implementation seems to one of the more complicated things out there. Surprised that IG has not offered their own example docs on how to do this with iOS. They only have docs for web based solutions.

Maybe something brewing there? Zillions of coders they have on staff. But for now, on the hunt for a (dare I say?) simple solution.

thanks a million. :-)

like image 535
Edward Potter Avatar asked Oct 27 '16 14:10

Edward Potter


1 Answers

For Swift 3:

Update: April 17 2017: Because of broken dependencies, the installation by Pods is no longer working. Therefore I have ripped the needed content and created a new Github project using a Bridging Header and stored all the needed files within the project. If you clone or download the github project, you'll instantly be able to login to Instagram.

To use those files in your project, simply drag and drop all the files from the SimpleAuth folder to your project, make sure to mark copy item if needed

enter image description here

Also you need to disable Disable implicit oAuth within the Instagram developer console.

enter image description here

Then you either copy/paste my code from the Bridging Header into your or you use mine. Set the Bridging Header at the Target's Build Settings.

enter image description here

Everything else works as before:

I have a struct for the Instagram Account:

struct InstagramUser {

    var token: String = ""
    var uid: String = ""
    var bio: String = ""
    var followed_by: String = ""
    var follows: String = ""
    var media: String = ""
    var username: String = ""
    var image: String = ""
}

The function to receive the token:

typealias JSONDictionary = [String:Any]
var user: InstagramUser?
let INSTAGRAM_CLIENT_ID = "16ee14XXXXXXXXXXXXXXXXXXXXXXXXX"
let INSTAGRAM_REDIRECT_URI = "http://www.davidseek.com/just_a_made_up_dummy_url" //just important, that it matches your developer account uri at Instagram

extension ViewController {

    func connectInstagram() {

        let auth: NSMutableDictionary = ["client_id": INSTAGRAM_CLIENT_ID,
                                         SimpleAuthRedirectURIKey: INSTAGRAM_REDIRECT_URI]

        SimpleAuth.configuration()["instagram"] = auth            
        SimpleAuth.authorize("instagram", options: [:]) { (result: Any?, error: Error?) -> Void in

            if let result = result as? JSONDictionary  {

                var token = ""
                var uid = ""
                var bio = "" 
                var followed_by = ""
                var follows = ""
                var media = ""
                var username = ""
                var image = ""

                token = (result["credentials"] as! JSONDictionary)["token"] as! String
                uid = result["uid"] as! String

                if let extra = result["extra"] as? JSONDictionary,
                    let rawInfo = extra ["raw_info"] as? JSONDictionary,
                    let data = rawInfo["data"] as? JSONDictionary {

                    bio = data["bio"] as! String

                    if let counts = data["counts"] as? JSONDictionary {
                        followed_by = String(describing: counts["followed_by"]!)
                        follows = String(describing: counts["follows"]!)
                        media = String(describing: counts["media"]!)
                    }
                }

                if let userInfo = result["user_info"] as? JSONDictionary {
                    username = userInfo["username"] as! String
                    image = userInfo["image"] as! String
                }

                self.user = InstagramUser(token: token, uid: uid, bio: bio, followed_by: followed_by, follows: follows, media: media, username: username, image: image)


            } else {
                // this handles if user aborts or the API has a problem like server issue
                let alert = UIAlertController(title: "Error!", message: nil, preferredStyle: UIAlertControllerStyle.alert)
                alert.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default, handler: nil))
                self.present(alert, animated: true, completion: nil)
            }

            if error != nil {
                print("Error during SimpleAuth.authorize: \(error)")
            }
        }
    }
}

Instagram also says:

Important

Even though our access tokens do not specify an expiration time, your app should handle the case that either the user revokes access, or Instagram expires the token after some period of time. If the token is no longer valid, API responses will contain an “error_type=OAuthAccessTokenException”. In this case you will need to re-authenticate the user to obtain a new valid token. In other words: do not assume your access_token is valid forever.

So handle the case of receiving the OAuthAccessTokenException

like image 65
David Seek Avatar answered Oct 14 '22 01:10

David Seek