OAuth 2.0 integration in iOS - ios

I have been trying for ages now to get OAuth 2.0 integration in my iPhone application.
I have searched and searched for libraries, tutorials, etc... But they have all lead me to a dead end. The main problem I have is that they either have deprecated code, or they just don't work or they have some documentation but its really hard to follow (for me anyway...).
The best OAuth2 library I could find for Xcode is this one: https://github.com/nxtbgthng/OAuth2Client
But the main problem with that one is it doesn't seem to do anything... I have followed all the documentation and instructions that came with it, but after building and running, it doesn't seem to authenticate....
So I guess my main question is: does anyone know of any good and up to date OAuth 2.0 tutorials for Xcode or any libraries for such a thing?
Because I am really struggling at the moment.... :(
Thanks for your time, Dan.
UPDATE 2: Here is my code (App Id and secret removed for security):
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
oauthClient = [[LROAuth2Client alloc]
initWithClientID:#"MY_CLIENT_ID"
secret:#"MY_APP_SECRET"
redirectURL:[NSURL URLWithString:#"app://instagram-callback/?code="]];
oauthClient.delegate = self;
oauthClient.userURL = [NSURL URLWithString:#"https://api.instagram.com/oauth/authorize/?client_id=ab6dc96859bf43b3a488199ec72d9964&redirect_uri=app://instagram-callback/?code=&response_type=code"];
oauthClient.tokenURL = [NSURL URLWithString:#"https://api.instagram.com/oauth/access_token/"];
[oauthClient authorizeUsingWebView:myWebView];
}
- (void)oauthClientDidReceiveAccessToken:(LROAuth2Client *)client;
{
LROAuth2AccessToken *token = client.accessToken;
[NSKeyedArchiver archiveRootObject:token toFile:#"Path/To/MyAccessToken"];
}
- (void)checkAccessTokenForExpiry:(LROAuth2AccessToken *)accessToken;
{
if ([accessToken hasExpired]) {
[oauthClient refreshAccessToken:accessToken];
}
}
- (void)oauthClientDidRefreshAccessToken:(LROAuth2Client *)client;
{
LROAuth2AccessToken *token = client.accessToken;
[NSKeyedArchiver archiveRootObject:token toFile:#"Path/To/MyAccessToken"];
}

In almost all projects I have used AFNetworking because it's very powerful
-why re-invent the wheel every time :)
Furthermore, it also has an OAuth2Manager which is quite easy to implement and works rock-solid.

In Instagram documentation says that there are two ways to authenticate. One Explicit (for server-side auth) and one Implicit, for auth in a client (without server).
You are using the Explicit one inside the app, try changing the userURL to https://instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=token and the tokenURL to http://your-redirect-uri#access_token=ACCESS-TOKEN.

You most likely cannot use a client secret in an iPhone App (because the client secret cannot be protected), you will need to authenticate through the services mobile app or mobile web site and then handle the redirect url, according to this link I found on the Uber api developer site:
http://aaronparecki.com/articles/2012/07/29/1/oauth2-simplified
There is some code on this page to do just that, which I am testing now:
https://medium.com/swift-programming/learn-nsurlsession-using-swift-ebd80205f87c
There is also some good information on the bottom part of this page: http://www.idmworks.com/blog/entry/getting-started-with-oauth2client-on-ios

I recently made simple pod https://github.com/kohtenko/KOSocialOAuth.
You can easily connect Instagram, VK or LinkedIn. Feel free to send Pull Request with any other OAuth endpoint.

Check out this for using the Instagram API: https://github.com/shyambhat/InstagramKit. In the comments I see that you're having trouble with the redirect - look into Xcode's Redirect URI's for help with that: What's a redirect URI? how does it apply to iOS app for OAuth2.0?

Related

Auth0 React JS Quickstart Not Requesting all scopes

I am currently using the react JS quick start available at the following link.
https://github.com/auth0-samples/auth0-react-samples/tree/master/Sample-01
About a year ago, I was able to repurpose it. That old app is still working fine, able to authenticate, authorize and also make calls to a custom API.
On the old app, I am getting all the scopes.
“scope”: “openid profile email read:profiledetails read:seeallquotes read:sitestats read:testperm1 read:testperm2”
Now, I have made a fresh copy of the react app using the quick start option, from the same auth dashboard as the old app. Updating the config file to match the old app config files. I get the following scopes
“scope”: “openid profile email”
Why am I not getting all the scopes as per the user login? Same user, on the old app, gets all the scopes. I believe, the new react app is not asking for all the scopes when it asks for token. But, I have updated all the scopes I need in the auth config.
Both apps - old and new - have the exact same auth file, and are linked to the same auth0 server, same custom api, same everything. I am also using the same user account for testing on both the apps.
{
“domain”: “removedonpurpose.us.auth0.com”,
“clientId”: “removedonpurpose”,
“audience”: “removedonpurpose”,
“scope”: “read:current_user update:current_user_metadata read:capquotes read:penquotes read:profiledetails read:seeallquotes read:sitestats read:testperm1 read:testperm2”
}
Why is this happening?
What else should be included in the react app to make it ask for all the scopes?
This question is related to the original question I posted on the Auth0 forums. Linking it here. https://community.auth0.com/t/scope-not-included-in-token-call/65173
Right after I posted this I discovered that the latest version of the react quick start makes some changes.
especially the following.
// Please see https://auth0.github.io/auth0-react/interfaces/auth0provideroptions.html
// for a full list of the available properties on the provider
// const config = getConfig();
// const providerConfig = {
// domain: config.domain,
// clientId: config.clientId,
// ...(config.audience ? { audience: config.audience } : null),
// redirectUri: window.location.origin,
// onRedirectCallback,
// };
I missed this part. in the old app, the configuration was done differently. It looked something like this.
<Auth0Provider
domain={config.domain}
clientId={config.clientId}
audience={config.audience}
redirectUri={window.location.origin}
onRedirectCallback={onRedirectCallback}
scope={config.scope}
>
<App />
</Auth0Provider>,
with the settings read directly from JSON.
Anyway, I went back to the old way for now. The quick start tutorial still shows the old options which threw me off as I was using the tutorial as reference and did not discover that they made changes.
Not blaming the tutorial. I should have investigated in the beginning.

AeroGear for iOS Facebook configuration

I inherited an app, and I am trying to understand the exact configuration differences between what Facebook wants and what is currently implemented.
In working to create a great Platform experience for everyone, we ask developers to ensure the apps they build comply with our Platform Policies. Your app APPNAME (AppId: APPID) doesn't comply with the following:
Platform Policy 8.2: Native iOS and Android apps that implement Facebook Login must use our official SDKs for Login.
Please make sure your iOS app is using the most recent version of our SDK for Login. You can find more information on our iOS SDK for Login and other Login-related products here: https://developers.facebook.com/docs/facebook-login/ios.
EDIT: In addition, Facebook also told me this:
Thank you for reaching out and for all actions taken so far. I am still able to view the FB login using unofficial SDK [refer to screencast].
My guess is that this is due to the configuration of OAuth2 in the authentication service.
It is setup like this:
private init() {
let keycloakHost = ServerConfigurator.sharedInstance.keycloakUrl
config = KeycloakConfig(
clientId: "app-name-mobile",
host: keycloakHost,
realm: "master",
isOpenIDConnect: true)
config.webView = .safariViewController
config.webViewHandler = self.webViewHandler
oauthModule = KeycloakOAuth2Module(config: config, session: KeycloakClient.session)
}
Whereas the aerogear oauth docs seem to suggest a different configuration is required for Facebook:
https://github.com/aerogear/aerogear-ios-oauth2
let facebookConfig = FacebookConfig(
clientId: "YYY",
clientSecret: "XXX",
scopes:["photo_upload, publish_actions"]
)
let oauth2Module = AccountManager.addFacebookAccount(config: facebookConfig)
let http = Http()
http.authzModule = oauth2Module
http.request(method: .get, path: "/get", completionHandler: {(response, error) in
// handle response
})
It also seems like the original developer is piping the input through to a Safari Webview, vs using the methods expected by the library. I'm not entirely why that is either. I think this may, in fact, be the cause of the issue Facebook has with the app.
Can anyone shed some light on this error? I'm trying to most efficiently deal with it as there is a very quick time limit (a week), and I'm not even sure if I am going down the right path here.
Any advice is highly appreciated.
EDIT: I am now using this version:
https://github.com/maciej-gad-benefex/aerogear-ios-oauth2
EDIT: This also needs to integrate with Keycloak identity provider
This library is not going to be maintained anymore. The last significant change was 2 years ago (Commits on Jan 13, 2017)
I really recommend you to replace this for AppAuth-iOS
It looks like Facebook is saying that you have to use the Facebook-supplied SDK for login, so in order to comply, you have to move to https://developers.facebook.com/docs/facebook-login/ios.

Remember App-Engine Sign-In on IOS Devices

I've been following this Google page that describes how to authenticate under IOS to an App-Engine (cloud endpoint) backend. That's fine. However, it seems to require signing in anew with each run of my program.
Is there any way to
skip the signin/authentication web-view in favor of some global resource,
remember previous signin/authentication information and re-use it, or
simplify the signin/authentication procedure by remembering the previous username
It would be nice if the IOS version could behave like the Android version which, of course, does not need a sign-in step because it's handled directly by the OS.
Thanks!
I've now worked this out. Not sure how I missed it in the documentation during my first pass.
See "Retrieving Authorization from the Keychain" at https://code.google.com/p/gtm-oauth2/wiki/Introduction
GTMOAuth2Authentication* auth =
[GTMOAuth2ViewControllerTouch
authForGoogleFromKeychainForName:AUTH_KEYCHAIN_NAME
clientID:IOS_CLIENT_ID
clientSecret:IOS_CLIENT_SECRET];
if ([auth canAuthorize]) {
// add existing auth to our GTLServiceFoo, cleverly named "fooEndpoint"
[fooEndpoint setAuthorizer:auth];
} else {
// go through sign-in dialog flow and add the auth resulting from that
...
}

Setting up YouTube access within app, stuck on retrieving url response

I can't find any answers or similar questions to my YouTube API puzzle and hoping someone can help.
My iOS app, which makes a video within it, needs to connect to a user's YouTube account so they can upload the video for others to see etc.
I've followed the API documentation and managed to connect to the authentication part where the user logs into their account, (code I used posted below).
It works in the sense it takes user to the login page for Google, when logged in the page asks if the user would like to authorise the app access to account, etc. When the user accepts though, I understand there should be data returned which gives the app authentication, the token code, so it can be used to upload videos later within the app.
My question is.... How do I retrieve this data? When I click accept it simply takes me to another webpage, but I don't know where to retrieve the info.
Thanks in advance for anyone who can point me in the right direction.
#define kAuthUrl #"https://accounts.google.com/o/oauth2/auth?"
#define kClientID #"client_id=xxxxxxxxxxxMyUniqueIDDetailsxxxxxxxxxx&"
#define kRediretUri #"redirect_uri=urn:ietf:wg:oauth:2.0:oob&"
#define kScopeUL #"scope=https://www.googleapis.com/auth/youtube.upload&"
#define kResponse #"response_type=code"
Above code placed in header file.
- (void)viewDidLoad
{
NSString *loginURL = [NSString stringWithFormat:#"%#%#%#%#%#", kAuthUrl, kClientID, kRediretUri, kScopeUL, kResponse];
NSURLRequest * urlReq = [NSURLRequest requestWithURL: [NSURL URLWithString:loginURL]];
[_webView loadRequest:urlReq];
[super viewDidLoad];
// Do any additional setup after loading the view.
}
From the YouTube API documentation it says
When this value is used, your application can sense that the page has loaded and the title of the HTML page contains the authorization code. It is then up to your application to close the browser window if you want to ensure that the user never sees the page that contains the authorization code. The mechanism for doing this varies from platform to platform.
Where "this value" refers to the redirect_uri I chose, as opposed to a local host redirect.
How can I sense the user has logged on to their account and pressed the "accept" button, and this now also leads me on to asking how to know this and then retrieve the code from the returned url while closing the browser.
Cheers, Jim.
My strong recommendation is to use the Google Toolbox for Mac OAuth 2 Controllers project to handle all the details of your OAuth 2 integration for you.

Secure Authentication: Rails WebApp and iOS App

i searched a long time but could only find really basic information, so i decided to ask here:
The simple thing is, that I wanna authenticate an iOS Application against a rails web Application.
I thought about something like HTTP Basic or Token based - but this isn't what I really want.
I wanna authenticate against OAuth from Facebook, Twitter and so on.
On the rails side this is really easy. Device with omniAuth did this job great.
But how shall I authenticate the iOS App with this method?
It would be great if anybody could give an more detailed view on how to do this.
I think you have two solutions.
1: WebView
Use WebView for OAuth request/response.
SHKOAuthView of ShareKit will help your understanding.
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
// "OAUTH_DID_FINISH_SUCCESS_URL" is URL your wab app display after finishing OAuth authentication successfully.
if ([request.URL.absoluteString isEqualToString:OAUTH_DID_FINISH_SUCCESS_URL])
{
// OAuth success
return NO;
}
return YES;
}
After finishing OAuth authentication with WebView, iOS app automatically save cookie(if web app save cookie), so iOS app can normally request/response to web app. Incidentally Android may not save cookie automatically, so token based authentication is better if you have to support Android app too.
2: RestKit
RestKit support OAuth.
I think Device is not the best solution for iOS Application with OAuth.
I think scratch authentication with omniAuth is better.

Resources