How do I persist login state for a user between my website and my chrome extension - google-chrome

I built a Chrome Extension, where a login form is displayed as a side bar using content scripts injection. I do not want the user to see this login form if the user is already logged in on the website and vice versa if the user logs in on the Chrome Extension and then visits the website, user should automatically log in.
I am returning tokens from the backend when a user successfully logs in.
My question is, what is the best way to store these tokens so both the content scripts in my extension and the website have access to the token to check to see if the user is already logged in.
As far as I understand I have localStorage, ChromeStorage but I do not know if they are shared between the tabs of the browser and the extension.
Any direction is highly appreciated.
Thank you.

If you're returning tokens, a reasonable way to do it would be to inject a content script into pages that match the callback URL containing the token, extract it and save into chrome.storage. It is shared between the content script and all other extension contexts.
Do note: chrome.storage is not exactly secure: it's not encrypted on disk, and can be snooped upon with Dev Tools. Then again, the token is normally stored in the cookie store, which can be likewise examined even without access to the (slightly) more secure password storage.
Perhaps the only more secure way to keep the token in the extension is chrome.identity API, but then you have to login separately, defeating your goal.

Related

Need refresh token without using consent screen in G Suite

We are using G Suite API with our Micro service for document editing, and we have a different data center and also different db. now once user comes to my application and trying to open document first time then google give consent screen based on that i can get refresh token and access token and i store into one data center.
But problem is that if user comes from another instance which use different data center with different db and user trying to open document with old credentials then google doesn't give any consent screen so i am not getting user's refresh token.
1) So is there any way to get refresh token without using consent screen?
2) Is there any way to identify if user comes from different sub domain then i need to provide consent screen for that?
It might be possible to use the prompt=consent option to force a re-prompt for auth, even though the user has already authorized your app.
See https://developers.google.com/identity/protocols/OAuth2WebServer#creatingclient
You can identify the user's domain using the hd parameter [1] and you can request a refresh token without the consent screen after the domain admin has configured domain wide delegation by installing your application from the GSuite Marketplace [2].
[1] https://developers.google.com/identity/protocols/OpenIDConnect#hd-param
[2] https://support.google.com/a/answer/172482?hl=en
When you request an OAuth Flow (access_type=offline`), a Refresh Token is returned to your application. This only happens once (obtaining a Refresh Token). Your application is expected to save the Refresh Token for future needs.
In your use case, one of your systems completed the authentication and the user has moved to a different system. You will need to reauthenticate with prompt=consent, access_type=offline. You will not get another Refresh Token without reauthenticating.
I spent a lot of time on this issue last November. Here is a link which has lots of details on this problem.
Any application can only have one valid refresh token for a user. You can request for a new refresh token using the prompt=true&access_type=offline on the request as said by #John. But every time the previous one will become invalid.
Based on you comments on the other answers, I'm assuming creating a new micro service that returns the token to the one being used is not a possibility (that would be my recommendation)
You asked "to identify if user comes from different sub domain"...
If those applications are for end users of gmail.com accounts, you can treat them as different applications and configure different projects on the developer console.
It will be a bit of a pain when enabling new APIs, I would recommend doing that from a script that replicates to all application needed.
If your end users are from companies using GSuite, you can have your app installed as domain-wide application (either manually or from GSuite Marketplace). In that case you can use just client side authentication to get an id_token, send the token to the server and use a service account to impersonate the user in any given service without worrying about any token from them.

Second authorization with same scope and offline access_type has unexpected permission dialog

If I specify access_type=offline in the auth url and a user attempts to auth a second time I get a box that says it is asking for offline access.
I would have expected it to be already authorised and so not require additional permissions
Any ideas?
Edit:
A bit more info. The first time around it makes no mention to the user of needing offline access. I would have thought the offline permission to be mentioned in the original auth anyway.
Edit 2:
Some more info on my use case. It is possible in our system for a person to have two accounts but then use the same google drive account. This means that we have no way of knowing that user has already authorized with google and so have to present the authorization again for the second user.
The first time around (for user 1) you are told that the app is asking for :
View and manage Google Drive files that you have opened or created
with this app
View and manage the files and documents in your Google
Drive
The second time around (for user 2) you are told the app is asking to:
Have offline access
This seems wrong to me.
As an aside:
The whole "have offline access" statement is very confusing for a user and also quite misleading. Most people assume this means the app can read the contents of your pc. In fact it means that the app can authenticate with your account with out you being there (i.e. using a refresh token).

box.com api OAuth authentication

Either I'm dense, or the docs assume I already know what they're telling me, but I need some clarification on doing authentication for a box.com app. I really don't understand whate's going on. As I read it:
the app running on the user's machine sends a request to Box, including all the little secrets (Which aren't all that secret any more if the user knows how to read the code).
The user is directed to the Box login page, which then sends the user to my server (with no page specified) attaching an authentication code.
The app somehow magically gets that code back from my server and sends a request to Box for the access token.
Box sends the access token to my server?
The app again magically gets the access token from my server and sends its APT requests.
Obviously I got lost somewhere.
And, why do I have to have a server involved in the process? The article on making a JavaScript app refers to a direct request for a token. Is there documentation on that somewhere?
You register your application on Box
After registration you receive clientId and clientSecret once on Box website
You hardcode your credentials somewhere in your application
First time your application needs to access Box API it should redirect user to https://www.box.com/api/oauth2/authorize, specifying your clientId, clientSecret and redirectURI as parameters. About redirectURI see below.
The box.com website opens. User enters his own credentials in the web form on box.com
User allows your application to access his files via API on the box.com website
Box redirects user back to you application using redirectURI specified before. One of the parameters to this request is "code". This is a very short-lived (30 seconds) access code that is only aligable for obtaining real access token.
During next 30 seconds your application should make another call to Box API to next URL: https://www.box.com/api/oauth2/token, specifying the previously obtained code. If everything was correct, your application receives an access_token, a refresh_token and "expires" values.
Now your application can make requests to Box API, specifying access_token every time
access_token expires in number of seconds, specified in "expires" field. It should be about 3600 seconds or 1 hour. Each time your application sees that access_token has expired, it should make another request to Box with the refresh_token and obtain a fresh access_token for another 1 hour.
refresh_token itself expires in 14 days
Note: if you develop a desktop application, then you should open browser for user on the step 4, redirectURI should be something like http://127.0.0.1:8080/Callback and you should run a small webserver just to catch the redirect with the code as in step 7.
Box requires that you specify a redirect_uri in your application's profile, and it must be an HTTPS URL.
As a result, it is not possible to use box with what google's oauth2 documentation calls "Client Side" or "Installed" applications, only "Web Server Applications" are allowed. Web Server applications do not have the secret leaking problem, because only the server knows the secret. You can pass the access token from your server to javascript on the client after
the oauth transaction is complete, if you want the client to make api requests directly.
In your question you are not totally clear in what you are actually trying to produce.
I however suspect that you are trying to write a client application what needs to authenticate to box using the OAUTH2 solution they have delivered in API V2.
If this is for an IPhone for example BOX has a great example of how to handle it.
In a WinForm application you would need to capture the resulting code sent back by box in the browser1.isnavigating event.
Windows console application you register a custom URI registration to collect the code.
Neither of these need to be registered in the API developers Application on box as you would pass the redirect required in the request to box.
If this does not point you in the right direction and your writing a .NET app then post again and I will try to clarify a little more.
Box requires some form user interaction which is short sighted in my opinion but try a web service that simulates a user interaction which then you can save/pass the token to your application to sync up with the Box "Cloud".

oauth for html5 enabled devices

I'm building a webapp specifically for iOS and Android devices which requires user to sign in with their Facebook or Twitter accounts. I have it setup so that initially they're redirected to the appropriate login page and upon successful completion my provided calllback url is triggered.
Because I want to implement a single sign on, I will be storing on the user's device the access token that I received so they can easily access the webapp without having to sign in again next time.
My question is this: is it better to store it as an html4 cookie from the server side? Or is it better to insert it as a hidden input in the home page and have javascript on the client grab it and store it with the new local/sessionStorage? And if the latter, which type of storage would be better for this type of data that I would like to save?

appNotInstalled when the refresh token is missing?

Lately I've been noticing a strange behavior when trying to access Drive specific actions. The use case is as follows:
the user installs the Chrome Store application
the user launches the application, we get a refresh token for the email and the profile scopes
the user wants to export a document into Google Drive
error message 403: appNotInstalled is returned
If the user goes to Google Drive and opens a file from there using our application, they are redirected to a new authorization dialog that asks for the email, profile, drive scopes. After the user grants access, the initial export also works fine. My assumption is that the initial refresh token that we had was no longer valid, even though exchanging it for an access token worked and the refresh tokens don't expire.
Shouldn't we receive a more descriptive error message in this case that would suggest that we simply have to redirect the user to the authentication dialog instead of the Chrome Store listing?
The issue might be that you are using a different client id/secret than the one you registered for the Drive SDK.
A quick test would be to:
revoke all granted tokens for your application on your test account
visit your application from the New Tab Page, it should redirect you to the authorization page: copy the URL you generated (do not approve).
visit your application from Drive, it should redirect you to the authorization page: copy the URL (do not approve).
Make sure the 2 URLs are identical (they should be), especially look for similarities in the scope and client_id query parameters.