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"]];
Related
I've recently been experimenting with the Coinbase iOS SDK and I've been having issues retrieving a user's Ethereum, Litecoin and Bitcoin Cash balances and historic transactions. Currently, I've only managed to do this with Bitcoin, USD and EUR, which seems to be consistent with the behaviour of the demo app supplied by Coinbase.
I have configured an application on the Coinbase API Access page using OAuth2 and the generated client ID and secret are being used within the app.
The issue seems to stem from the fact that I modified the Coinbase iOS SDK to allow me to pass the account parameter as
‘all’. This, I had hoped, would allow me to view details of all user accounts (ETH, BTC, LTC etc.) however, I only get BTC, USD and EUR when calling ‘getAccountsList’ on the Coinbase object.
NSString *accessToken = [response objectForKey:#"access_token"];
Coinbase *client = [Coinbase coinbaseWithOAuthAccessToken:accessToken];
[client getAccountsList:^(NSArray *accounts, CoinbasePagingHelper *paging, NSError *error) {
for (CoinbaseAccount *account in accounts) {
// Only BTC, USD and EUR are in the accounts array at this point.
}
}];
This is surprising as the permissions request page correctly asks the user for all wallets, as you can see in the screenshot below:
I suspect a solution to this would be to use API keys, as you are able to specify exactly which accounts to grant access to. I plan to distribute the app however, so this technique should not be used.
Here is an example of the URL I am sending:
https://www.coinbase.com/oauth/authorize?response_type=code&client_id=CLIENT_ID_GOES_HERE&account=all&scope=balance%20transactions%20user&redirect_uri=com.example-name.example-app.coinbase-oauth%3A%2F%2Fcoinbase-oauth
Does anyone know how I can request access to all of a users accounts using OAuth and be able to retrieve details for each? Is the scope I defined incorrect in some way? The only alternative I can think of would be to request access one by one to each wallet and store individual access tokens. This wouldn't be a great user experience however.
Thanks!
Add the parameter
account=all
to the oAuth endpoint: https://coinbase.com/oauth/authorize?account=all&response_type=code...
Here are the details: https://developers.coinbase.com/docs/wallet/coinbase-connect/permissions
Coinbase Connect applications can request different access to user’s wallets. This access is defined by account parameter on OAuth2 authorization URL. Available options are:`
select - (default) Allow user to pick the wallet associated with the application
new - Application will create a new wallet (named after the application)
all - Application will get access to all of user’s wallets
I believe the iOS SDK is in need of an update. It still connects to old API version.
I'm using the original Coinbase SDK. No fork. in stead, next to the wallet:accounts:read scope, I also add ["accounts": "all"] as meta argument to the startAuthentication method.
AND. I am NOT using the getAccountList method, but instead the more general .doGet method with the api v2 accounts endpoint (so coinbase.doGet("https://api.coinbase.com/v2/accounts", parameters: nil) {(response, error) -> Void in
This gives me account info for all wallets. You do need to do some json processing on the response object in this case though.
First if you don't have one, you need to create an account on Coinbase
Then, please take a look first on the Coinbase digital api documentation, and I agree with you that it maybe easier to use the API to get data (if the target account is only your own personal account)
Because according to Coinbase:
API Key authentication should only be used to access your own account or merchant orders. If your application requires access to other Coinbase users’ accounts, do not use API Key. To securely access other Coinbase users’ accounts, use Coinbase Connect (OAuth2)
You have two possibilities:
USE API
Assuming user has grant wallet:accounts:read to the API key ( which allow you to List user’s accounts and their balances) according to the wallet permission documentation.
Once done, you may use the official wallet client libraries for iOS - coinbase is available through CocoaPods - by adding the following line to your Podfile: :
pod "coinbase-official"
USE OAuth2 PROTOCOL
According to this,
It is a slightly more complex integration than the API Key authentication method, but is more flexible. OAuth2 works well for web applications, as well as desktop and mobile apps.
You will find a lot of informations in the coinbase-connect integrating documentation, and you may also take a look on the official OAuth2 protocol website first.
Assuming you are OK with OAuth2, you will also have to ask user to grant you permission before requesting data.
As you need access to user wallet, you still have to request access token and add a scope parameter in the authorization request (Comma separated list of permissions (scopes) your application requests access to), if you need to see the full scopes list please refer yourself to this page.
The required scope is the same as API method: wallet:accounts:read, and your request will look like this:
GET https://www.coinbase.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URL&state=SECURE_RANDOM&scope=wallet:accounts:read
After a successful request, a valid access token will be returned in the response (like this):
{
"access_token": "6915ab99857fec1e6f2f6c078583756d0c09d7207750baea28dfbc3d4b0f2cb80",
"token_type": "bearer",
"expires_in": 7200,
"refresh_token": "73a3431906de603504c1e8437709b0f47d07bed11981fe61b522278a81a9232b7",
"scope": "wallet:user:read wallet:accounts:read"
}
Once you get the access token, you can make any API call corresponding to the previous scope if you add the following header to the request:
Authorization: Bearer 6915ab99857fec1e6f2f6c078583756d0c09d7207750baea28dfbc3d4b0f2cb80
Finally, you may refer to the API reference documentation to see all possible API call and the relative scopes.
To conclude, you need to grant permission, then list the user accounts, then you may get any account resource:
Account resource represents all of a user’s accounts, including bitcoin, bitcoin cash, litecoin and ethereum wallets, fiat currency accounts, and vaults.
Regards
Still no luck.
Tried with adding param account=all. It gave me access to all wallets (exactly same as op). However, in code, I can only get BTC Wallet, BTC Vault, EUR Wallet and newly created BTC Wallet. The new wallet was created by adding param account=new.
Tried with adding param account_currency=BTC,ETH and chose ETH Wallet on oAuth authorization. Did getAccountsList which returned 0 objects and no errors from the server.
Tried with revoking all API application access in my Coinbase account (Settings->Security).
Scope: balance transactions user
Endpoint: .../oauth/authorize?account=all&response_type=code&client_id=%...
I am working iOS app which is using Salesforce oAuth for login.
I would like to load one VF page url in web-container which requires the login to access. As I am already having valid oAuth token, How can I access VF page (salesforce) by passing access token on header request.
If you are using framework of SalesForce iOS SDK and you have a valid OauthToken :
SFOauthCordinator class has a method called [coordinator authenticateWithCredentials:[[SFAccountManager sharedInstanceForAccount:#"user"]credentials]]. This source line gives you a login session by using the existing oAuthToken.
I'm trying to integrate Google with Amazon Cognito in an iOS application using the Google Sign-In SDK but I can't seem to figure out how to obtain the JWT id token correctly. Everything is set up correctly, I believe, as both Google Sign-In and Cognito work independently.
I am setting up the GIDSignIn like this.
[GIDSignIn sharedInstance].scopes = #[kGTLAuthScopePlusLogin, kGTLAuthScopeDrive];
[[GIDSignIn sharedInstance] setClientID:kClientID];
[GIDSignIn sharedInstance] setServerClientID:kServerClientId];
and then to get the id_token, as specified here with the exception being that I am using Google Sign-In and not Google+ signin, which has no GTMOAuth2Authentication.
- (void)googleSignedIn:(GIDGoogleUser *) user
{
NSLog(#"AWSManager: Google signed in, id token = %#", user.authentication.idToken);
NSString *idToken = user.authentication.idToken;
self.credentialsProvider.logins = #{ #(AWSCognitoLoginProviderKeyGoogle): idToken};
but the idtoken is not json formatted web token, it is just a hunk of characters. AWS throws this error --
AWSiOSSDKv2 [Error] AWSIdentityProvider.m line:185
| __51-[AWSAbstractCognitoIdentityProvider getIdentityId]_block_invoke169
| GetId failed.
Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=9
"The operation couldn’t be completed. (com.amazonaws.AWSCognitoIdentityErrorDomain error 9.)"
UserInfo=0x8fa5eb8e4e40{__type=NotAuthorizedException, message=Token is not from a supported provider of this identity pool.}]
I have no idea what I'm to do. I'm pretty new to objective-c and have done all of this on Android before. On android I did:
String mServerClientId = "audience:server:client_id:xxxxxxxxxx.apps.googleusercontent.com"
String token = GoogleAuthUtil.getToken(getApplicationContext(), accountName, mServerClientId);
to retrieve the tokens, but far as I can tell there's nothing like that on iOS. I can provide more information if needed.
Thanks!
From the error it looks like the clientId is not setup correctly in the identity pool configuration. Google has different client ids for each platform, to support multiple client ids, you should use the Cognito's support for generic OpenID Connect Identity Providers. Please follow these steps:
Go to AWS IAM Console's identity provider section .
Create an OpenId Connect Identity Provider with provider URL as https://accounts.google.com and Audience as one of the client Ids.
Follow the steps to create identity provider and later you will have an option to add additional client ids.
Go to Amazon Cognito Console.
Create or edit an identity pool and add the OpenID connect identity provider to the pool. This will allow you to trust multiple client Ids.
You can follow the Cognito documentation for Google login here and OpenID connect providers here.
Additionally, the token which you are getting is actually Base64 encoded. It has three parts separated by a period.
The algorithm which is used.
The payload.
The signature which Cognito validates.
You can use this cool tool for decoding the tokens.
Thanks,
Rachit
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.
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. :)