Remember App-Engine Sign-In on IOS Devices - ios

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
...
}

Related

Google Identity Services: How to preserve session

I'm migrating a web app that interacts with the google drive js api to the new Google Identity Services API and following this quickstart guide. GIS is mandatory, since the old one will no longer be in use from March 2023.
In this guide, there is only one small note mentionning to preserve the logged in state after page reload:
Note: After the initial user authorization, you can call gapi.auth.authorize with immediate:true to obtain an auth token without user interaction.
However, there's no clear code example how to do that, furthermore one can find in the migration guide, that gapi.auth2.authorize() is deprecated.
Using One Tap (a div with the id "g_id_onload") is not a solution, because I need an extended scope (to access later on google drive)
Storing the access token in localstorage (as mentionned in some threads) is no option, since it violates the oauth model
Calling requestAccessToken() after every page reload without user interaction is not an option, because 1st the popup is not shown at all (blocked in all major browsers) and 2nd if allowed the popup is shown and hiding immediately (bad ui)
Can somebody give me an example where GSI is used via JS that preserves sessions through page reloads?
It seems that Google Identity Services is not yet production ready or am I wrong?
In order to help:
Google 3P Authorization JavaScript Library: in this link we can check all the methods the new library has (it does not refresh token, etc..)
This doc says the library won't control the cookies to keep the state anymore.
Solution
Firstly I need to thanks #Sam O'Riil answer.
As Sam described: "you can somehow save access token and use it to speed-up things after page reload."
Given the the Google's exampe, we should call initTokenClient in order to configure the Google Auth and the requestAccessToken to popup the auth:
tokenClient = google.accounts.oauth2.initTokenClient({
client_id: 'YOUR_CLIENT_ID',
scope: 'https://www.googleapis.com/auth/calendar.readonly',
prompt: 'consent',
callback: tokenCallback
});
tokenClient.requestAccessToken({prompt: ''})
In your tokenCallback you can save the credentials you get somehow, e.g.:
const tokenCallback(credentials) => {
// save here the credentials using localStorage or cookies or whatever you want to.
}
Finally, when you restart/reload your application and you initialize the gapi.server again, you only need to get the credentials again and set token to gapi, like:
gapi.load('client', function() {
gapi.client.init({}).then(function() {
let credentials = // get your credentials from where you saved it
credentials = JSON.parse(credentials); // parse it if you got it as string
gapi.client.setToken(credentials);
... continue you app ...
}).catch(function(err) {
// do catch...
});
});
Doing it, your application will work after the reload. I know it could not be the best solution, but seeing what you have and the library offers, I think that's you can do.
p.s.: the token expires after 1 hour and there is no refresh token (using the implicit flow) so, you will have to ask the user to sign-in again.

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.

Flutter Auth on iOS hangs when retrieving token with code exchange

I have the following code in flutter trying to retrieve an oauth2 token via auth code with PKCE flow:
final FlutterAppAuth appAuth = FlutterAppAuth();
final request = AuthorizationTokenRequest(
B2C_CLIENT_ID,
B2C_REDIRECT_URI,
discoveryUrl: 'https://$B2C_DOMAIN/.well-known/openid-configuration',
scopes: ['openid', 'profile', 'offline_access'],
// promptValues: ['login']
);
final AuthorizationTokenResponse result =
await appAuth.authorizeAndExchangeCode(request);
When this code is run in iOS, the browser opens and I can see it tries to load the signin page, but then immediately closes. No exceptions are thrown or anything. The code basically hangs at appAuth.authorizeAndExchangeCode almost like it doesn't know that the browser has closed.
I am not sure what could be causing this.
The code correctly determines the url for showing credentials using the discoveryUrl (i.e. it makes the http request first using the discoveryUrl) but not sure why it basically hangs after.
I am using azureb2c for authentication here.
Edit
Ok turns out this is a problem with using azure b2c in particular as tried it with a different identity provider and works fine.
I managed to locate the issue and fix it now a login page shows in the browser. After entering credentials, browser closes, but code still hangs on appAuth.authorizeAndExchangeCode(request); and does not proceed.
Also found existing issue. on github: https://github.com/MaikuB/flutter_appauth/issues/182
I managed to solve this following the below answer on the Github repository of the flutter_appauth plugin.
https://github.com/MaikuB/flutter_appauth/issues/182#issuecomment-840707729
Eventually, all I had to do was to add a trailing slash to the redirect url parameter in AuthorizationTokenRequest.
(It looks like Azure AD appends on a trailing slash to the redirect url which causes the validation in AppAuth to fail).
My app worked correctly with the slash both on Android and iOS.
P.S. If this doesn't work for someone, try to adjust the redirect url in your App Registration as suggested in the respective thread https://github.com/MaikuB/flutter_appauth/issues/223.
I suspect this is related to the call to resumeExternalUserAgentFlow, so here is a plan of action for you:
Follow the steps in my blog post to get the AppAuth Swift + Carthage sample working - which also uses a Private URI Scheme. Use my online configuration details as specified in the blog post and you should have a working solution. I have just verified that my instructions still work.
Update the same sample to use your Azure AD configuration and see if it still works. If so then there is nothing wrong with AppAuth and the problem is in the Flutter layer.
If the Swift sample fails when you update to Azure AD configuration, add some print messages for the URL being supplied to resumeExternalUserAgentFlow in the AppDelegate class, and see if this is different to the original redirect URI. If the redirect URIs are different, reset to the original value and hopefully that will resolve things.

Why is my Google OAuth2 Sign in working, disregarding of my apps signing keystore

In our app we are using the Google Drive REST API. To authenticate, we're using Xamarin.Auth with the following configuration
var authenticator = new OAuth2Authenticator(<our client ID>,
null,
"https://www.googleapis.com/auth/drive",
"https://accounts.google.com/o/oauth2/v2/auth",
<our redirect url>,
"https://www.googleapis.com/oauth2/v4/token",
null,
true);
The login is presented using
var loginPresenter = new OAuthLoginPresenter();
loginPresenter.Login(authenticator);
(this is not the actual code, since the authorization is encapsulated in a class and the authenticator and the presenter are injected, but basically this is what we're doing).
This will open a login form in a browser and allow the user to login, resulting in the form calling back our app with a OAuth2 token. Everything works like a charm.
Our client ID has been created using the hash of our debug keystore. According to the docs and other questions (see here and here), this should cease to work in release configurations when the app is signed with a different keystore. Anyway, having signed the app with our internal testing AdHoc keystore, the login form still works without any issues. Actually I do not see how it should not. After all, all we do is opening a website in a system browser control, hence I do not understand how the website is supposed to get our apps hash.
Since the linked questions lack details, I can't see how they are different to our situation, but I somehow assumed Google OAuth to do some black magic to ensure that the hash matches. Is there any reason that this works for us? Can we expect it to keep working after it's been uploaded to Google Play or is there any risk that it stops working?

Auto login in dropbox folder with OAuth

Only for internal use i need to display the content of our dropbox folder in a tableview inside our app without show for the login screen and handle back the authentication url.
In all the example i've found only the reference to
#import <DropboxSDK/DropboxSDK.h>
DBSession *dbSession = [[DBSession alloc]
initWithAppKey:#"INSERT_APP_KEY"
appSecret:#"INSERT_APP_SECRET"
root:INSERT_ACCESS_TYPE]; // either kDBRootAppFolder or kDBRootDropbox
[DBSession setSharedSession:dbSession];
and after tha the authentication is handle as url call back from the web page of dropbox.
but there is a way of handle the different part to the autenticantion and keep them in code?
May be could be easily handle with direct api call ?
In the dropbox "app console" i've found a "Generated access token" but i'm not understand how to use.
Thanks for your help and for your time.
The Dropbox API was designed with the intention that each user would link their own Dropbox account, in order to interact with their own files. However, it is technically possible to connect to just one account. The SDKs don't offer explicit support for it and we don't recommend doing so, for various technical and security reasons.
However if you did want to go this route, instead of kicking off the authorization flow, you would manually use an existing access token for your app. (Just be careful not to revoke it, e.g. via https://www.dropbox.com/account/security .) In the iOS Core SDK you'd need to use:
- (void)updateAccessToken:(NSString *)token accessTokenSecret:(NSString *)secret forUserId:(NSString *)userId;
Again though, this isn't a good idea. Since this would be a client-side app, any malicious user of your app could extract the access token and use it to bypass any access restrictions your app attempted to enforce. For example, they could access content they shouldn't or add or replace content with a malicious payload that other users would access.
Unless Dropbox changed their API recently, the user must manually supply a username / password. This can be done by popping out to the Dropbox app or using a Dropbox web view. You can not programmatically supply a default username / password.

Resources