I'm trying to get access to the Google Drive API using RestKit on iOS but I'm having problems with the Oauth authentification.
I've been following the Wiki page they have on the subject here:
Oauth Support On RestKit
Basically we create the client like this:
oauthClient = [RKClientOAuth clientWithClientID:[Client Id] secret:[Client Secret] delegate:[Your Delegate]];
[oauthClient setAuthorizationCode:[User Authorization Code]];
[oauthClient setAuthorizationURL:[Authorization Endpoint]];
[oauthClient setCallbackURL:[Your application callbackurl]];
[oauthClient validateAuthorizationCode];
And we receive an access token on the delegate in the method
- (void)OAuthClient:(RKOAuthClient *)client didAcquireAccessToken:(NSString *)token
Here we can create an ObjectManager to make the requests and all the other operations
RKObjectManager* objectManager = [RKObjectManager sharedManager];
objectManager.client.baseURL = #"YOUR API URL";
objectManager.client.OAuth2AccessToken = #"YOUR ACCESS TOKEN";
objectManager.client.authenticationType = RKRequestAuthenticationTypeOAuth2;
With all this I have encountered a few problems.
First is how do we obtain the authorization code needed here:
[oauthClient setAuthorizationCode:[User Authorization Code]];
I haven't had problems with Client Id, Client Secret, Authorization Endpoint, Callback URL and API URL as they are provided mostly in the google console API but I don't know how to obtain that.
Second is the Access Token would be a temporal Access Token or a Refresh Token as they are named in the google API? If it's the first, how can we obtain a Refresh Token?
I've been trying to do this with RestKit but there may be better ways so I'm open to other ideas. I can't find much information about Oauth support in Restkit.
Thanks beforehand
You must use Google ObjectiveC Library in order to access Google Drive APi.
https://developers.google.com/drive/quickstart-ios
You can use Google's Objective-C client library for the Drive API, including OAuth 2 sign-in.
http://code.google.com/p/google-api-objectivec-client/
You start with your client ID and client secret, you direct the user to the resource owner's authorization server. The authorization server and the user validate each other and your app is returned an Authorization Code. You go back to the authorization server and exchange the Authorization Code for an Access Token.
If the Access Token is time boxed, then you would use the Refresh Token to request a new Access Token when you discover that the Access Token has timed out.
Related
I'm trying to implement the authorization code model using the Google Identity Services SDK, as described in Use Code Model. I would like to use the popup mode.
I managed to initialize the code client and receive an auth code with this Javascript code:
tokenClient = google.accounts.oauth2.initCodeClient({
client_id: CLIENT_ID,
scope: SCOPES,
callback: '', // defined later
ux_mode: 'popup',
})
...
tokenClient.requestCode({prompt: 'consent'});
When I receive the auth code in my callback, I relay it to an endpoint on my platform, as described in Step 5: Exchange authorization code for refresh and access tokens and I try to exchange the auth code for a refresh and access token in Python:
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
'client_secret.json',
scopes=scopes,
state=state
redirect_uri=redirect_uri
)
flow.fetch_token(code=code)
The problem is that I use this code with an empty redirect_uri, I get an error "missing redirect_uri parameter". If I specify a redirect URL defined in Google Cloud Console, I get an error "redirect_uri mismatch". And if I try to use the same redirect_uri as the one sent in the initial popup request (Google seems to use storagerelay://... in this case), I get an error that "it doesn't comply with Google Oauth2 policy".
It appears that in any authorization flow when you get an authorization code on the client side and then pass that to your server for token exchange you have to use the string literal "postmessage" as your setting for redirect_uri.
flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file(
'client_secret.json',
scopes=scopes,
state=state
redirect_uri="postmessage"
)
flow.fetch_token(code=code)
This very important fact seems to be curiously absent from the documentation from most of the google client libraries, but it works for me. Hope this helps!
I would like to know is there any way or possibility to implement authorization code grant type as Authroizer in securing API gateway? As is searched, 'Authorization code' grant type is most recommended for securing API.
i found below article which explain's using cognito 'client credentials' as grant type to secure the api gateway,
https://medium.com/#awskarthik82/part-1-securing-aws-api-gateway-using-aws-cognito-oauth2-scopes-410e7fb4a4c0
I tried the similar way to create an API gateway, where i have done following integration:
Created user pool 'UI Hosted' in cognito with the grant type - 'Authorization code'
Add the resource server
Choosed default scopes as i don't want to add any new scope
Associated call back uri
Now iam able to access the login page to sign up and sign in and it return the 'Authorization code' in the call back uri
In API gateway
I created an API and integrated some mock response
Attached above user pool as Authorizer in the api gateway and deployed
Now when i invoke the api without passing token, it returns 'Unauthorized'
So i used below approach to extract the access token from cognito
How programtically exchange the authorization code to get the access token from cognito using python
And passed the token in the api header using post man, but still i am getting 'Unauthorized' response
So would like to know what needs to be done in api gateway in order to verify the token or what went wrong in this approach..?
Appreciate if anybody can help on this?
Thanks
Your API's role is to just deal with incoming access tokens from API clients. The API doesn't care what flow was used to get the token. Here is by far the most common behaviour:
UI logs the user in using Authorization Code flow - usually the PKCE variant
This involves the UI calling the Authorization Server - eg AWS Cognito
Once login completes the UI calls the API Gateway URL with an access token / JWT
The API then needs to validate the access token by verifying its signature
Here is some sample code in case it helps:
Lambda Authorizer Code to Verify Cognito Tokens
Web UI Code to implement Authorization Code Flow
AWS API Gateway has built in support for Cognito authorizers as in the screenshot on the left below.
For more control over behaviour you can instead create a custom lambda authorizer in code, which returns an AWS policy document, as in the screenshot on the right. My blog post and the above source code link has some further details, though it is quite detailed / advanced.
finally i got the answer here..
https://aws.amazon.com/blogs/mobile/understanding-amazon-cognito-user-pool-oauth-2-0-grants/
so i created a simple flask logic here to exchange the auth code to get the 'id_token' from cognito, which further can pass in the api header to get the response.
def getToken(auth_code):
response=''
try:
print("Code is", auth_code)
response = requests.post(url + '/oauth2/token',{'Content-Type':'application/x-www-form-urlencoded', 'grant_type': grant_type, 'client_id': App_client_id, 'code': auth_code, 'redirect_uri': 'http://localhost:5000/login'})
if response.status_code != 200:
return "Not a valid response"
print("Response is", response.json())
token_value = response.json()
print("Token value", token_value['id_token'])
return token_value['id_token']
except TypeError as e:
print("Error is",e)
I'm using MSGraph SDK iOS to login users with their Office365 accounts.
My end goal is to get:
refresh token
user details
id token (id_token as described in Azure Active Directory (AAD) endpoint documentation)
Using sample app I was able to login user, get a refresh token and user details (via [[[[MSGraphClient client] me] request] getWithCompletion:...]) but I can't find id_token anywhere.
Also, the Android version of the app I'm working on is using https://outlook.office.com/api/v2.0 as a base URL for SDK and I'm trying to change it also in iOS app from https://graph.microsoft.com/v1.0/.
I might be missing something obvious or important in docs or sample app, sorry if that's the case.
Question is: how to get id_token in MSGraphSDK on iOS?
UPD:
Here's code I'm using:
[NXOAuth2AuthenticationProvider setClientId:<clientId> scopes:#[#"https://graph.microsoft.com/Files.ReadWrite", #"https://graph.microsoft.com/Calendars.ReadWrite", #"openid"]];
[[NXOAuth2AuthenticationProvider sharedAuthProvider] loginWithViewController:nil completion:^(NSError *error) {
if (error) {
return;
}
NSArray *accounts = [[NXOAuth2AccountStore sharedStore] accountsWithAccountType:#"MSGraph"];
NXOAuth2Account *account = accounts.firstObject;
}];
NXOAuth2Account doesn't have any property that can be connected with id_token. The question is how to get id_token from NXOAuth2Client or MSGraphSDK frameworks?
An id_token is only returned if you're using the OpenID Connect flow. To enable this, you need to add openid to the list of scopes you're requesting and id_token+code as your response-type.
Optionally you can also request email and profile if you want to get a more "complete" id_token.
One additional item to keep in mind, the tokens are not provided by the SDK. They are obtained from Azure Active Directory via OAuth. The SDK simply takes the token you've previously obtained.
You can obtain a token using just about any library that supports OAuth 2.0 but I suspect the sample you're looking at is using NXOAuth2AuthenticationProvider. Something along the lines of:
[NXOAuth2AuthenticationProvider setClientId:<clientId>
scopes:#[#"https://graph.microsoft.com/Files.ReadWrite",
#"https://graph.microsoft.com/Calendars.ReadWrite"]];
In order to obtain the id_token using the above example, you add the openid scope:
[NXOAuth2AuthenticationProvider setClientId:<clientId>
scopes:#[#"https://graph.microsoft.com/Files.ReadWrite",
#"https://graph.microsoft.com/Calendars.ReadWrite",
#"openid"]];
I'm trying to connect to Exchange using Javamail and OAuth. I'm using Javamail 1.5.3 and I referred to this.
1) The exchange account that I'm trying to connect to is within an org domain. I know that my OAuth token is valid since I'm able to make a Rest api request to https://outlook.office.com/api/v2.0/me to get the user profile using the token. My code looks like this -
Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true);
props.put("mail.imap.sasl.enable", "true");
props.put("mail.imap.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
Session session = Session.getInstance(props);
Store store = session.getStore("imap");
store.connect("imap-mail.outlook.com", "xxx#org.com", OAUTH_TOKEN);
I get (javax.mail.AuthenticationFailedException) javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] OAuth authentication failed
2) When I connect to an xxx#outlook.com account, I get 500:Internal Server Error and I'm not able to make the api request above to fetch the user profile using the OAuth token I received.
OK... so here is my code:
twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self];
[twitterEngine setConsumerKey:CONSUMER_KEY secret:CONSUMER_SECRET];
accessToken = [twitterEngine getXAuthAccessTokenForUsername:profile.twitterUserId password:profile.twitterPassword];
NSLog(#"Access token: %#", accessToken);
the console shows the access token returned just fine (so it seems to work)
eg. Access token: C8A24515-0F11-4B5A-8813-XXXXXXXXXXXXXX
but instead of accessTokenReceived method being called next on my delegate, it calls requestFailed with a 401. How can I be getting a 401 unauthorized and getting an access token back from the method call?????
xAuth, the process for exchanging a login and password for an access token, is a privilege for applications that verifiably meet Twitter's criteria: desktop or mobile applications that are otherwise unable to provide the entire three-legged OAuth flow. Out-of-band OAuth and custom URI schemes are still preferred over xAuth.
If you've exhausted other OAuth implementations and want to use xAuth, you can contact Twitter through api#twitter.com from an email address directly associated with the account owning the application. Include full details about your application, its user base, links to screenshots of it in action, and a detailed description on why this form of authorization is appropriate for your application. Inquires for xAuth are considered on a case-by-case basis and will not be granted to all applicants.
Implementors of xAuth must not store logins and passwords within their applications -- this is not a drop-in replacement for basic auth or a way to avoid implementing OAuth authentication.
Found the issue... for anyone else that has this problem... Getting your app approved for OAuth is only part of the process. Although it looks like you are done and the twitter page gives you your key and secret... there is one not-quite-so-easy-to-find next step. You must send an email to api#twitter.com and ask them to actually enable it.
That was fun figuring out. :)