Swifter-Reverse-Auth
Swifter-Reverse-Auth copied to clipboard
Twitter Reverse Auth extension for Swifter on iOS and OS X
Twitter Reverse Auth extension for Swifter
Swifter provides comprehensive interaction with Twitter API but lacks the ability to request OAuth access token and secret (when using ACAccount
) without user intervention. Twitter provides the reverse authentication mechanism (x_auth_mode = reverse_auth
) for this. Reverse authentication eliminates the need to repeat authorization request to the user (via regular OAuth workflow), after they have already authorized your app to use Twitter accounts serviced by iOS (or OS X).
You may not need to implement reverse auth if you are only going to use Twitter API within the app itself. Having access to OAuth access token and secret is useful when the application needs query Twitter API on the user's behalf on a third party machine, like a server.
If you are looking to implement this using STTwitter in a Swift project, this gist is for you.
Troubleshooting
xAuth
Twitter restricts the xAuth authentication process to xAuth-enabled consumer tokens only. So, if you get an error like The consumer tokens are probably not xAuth enabled.
while accessing https://api.twitter.com/oauth/access_token
, see Twitter's website https://dev.twitter.com/docs/oauth/xauth and ask Twitter to enable the xAuth authentication process for your consumer tokens.
Usage
let TWITTER_CONSUMER_KEY = ""
let TWITTER_CONSUMER_SECRET_KEY = ""
let twitterAccount = ... // An ACAccount instance obtained from ACAccountStore.
let swifter = Swifter(consumerKey: TWITTER_CONSUMER_KEY, consumerSecret: TWITTER_CONSUMER_SECRET_KEY)
// Step 1
swifter.postReverseOAuthTokenRequest({ (authenticationHeader) -> Void in
let swifterOSAccount = Swifter(account: twitterAccount)
// Step 2
swifterOSAccount.getAccountVerifyCredentials(false, skipStatus: false, success: { (myInfo) -> Void in
// Step 3
swifterOSAccount.postReverseAuthAccessTokenWithAuthenticationHeader(authenticationHeader, success: { (accessToken, response) -> Void in
// This is what you're looking for.
println("key: \(accessToken?.key) secret: \(accessToken?.secret)")
}, failure: { (error) -> Void in
println("postReverseAuthAccessTokenWithAuthenticationHeader error: \(error)")
})
}, failure: { (error) -> Void in
println("getAccountVerifyCredentials error: \(error)")
})
}, failure: { (error) -> Void in
println("postReverseOAuthTokenRequest error: \(error)")
})
ReactiveCocoa
Here's how I use it with ReactiveCocoa:
let twitterAccount = ... // An ACAccount instance obtained from ACAccountStore.
TwitterAPI.sharedInstance.requestReverseAuthenticationSignalForAccount(twitterAccount)
.deliverOn(RACScheduler.mainThreadScheduler())
.subscribeNext({ (accessToken: AnyObject!) -> Void in
println("accessToken: \(accessToken)")
}, error: { (error) -> Void in
println("error: \(error)")
})
class TwitterAPI {
let swifter: Swifter
init() ... // Setup Swifter with consumer keys
func requestReverseAuthenticationSignalForAccount(account: ACAccount) -> RACSignal {
return RACSignal.createSignal { subscriber -> RACDisposable! in
self.swifter.postReverseOAuthTokenRequest({ (authenticationHeader) -> Void in
let swifterXAuth = Swifter(account: account)
swifterXAuth.getAccountVerifyCredentials(false, skipStatus: false, success: { (myInfo) -> Void in
swifterXAuth.postReverseAuthAccessTokenWithAuthenticationHeader(authenticationHeader, success: { (accessToken, response) -> Void in
// TODO: Ascertain that accessToken is not .None
subscriber.sendNext([ "key": accessToken!.key, "secret": accessToken!.secret ])
subscriber.sendCompleted()
}, failure: { (error) -> Void in
subscriber.sendError(error)
})
}, failure: { (error) -> Void in
subscriber.sendError(error)
})
}, failure: { (error) -> Void in
subscriber.sendError(error)
})
return nil
}
}
}
Creator
Inspired by Nicolas Seriot's work on reverse auth in STTwitter.
License
Swifter-Reverse-Auth is licensed under MIT license. See LICENSE for details.