1hr time limit on tokens used for server-server authentication - google-oauth

Tokens obtained via OAuth 2.0 for service accounts expire after 1 hour.
If an HTTP session is still open while the 1 hour limit is reached (presumably due to many upload/download actions), will the connection stay alive until the session is closed?
Thanks.
--Lee

If you are using OAuth to authenticate users in your website, you probably are not even using the token after the initial exchange with the OAuth provider. Most frameworks will create a cookie based session, for how long this session is valid is up to your setup. Usually the default is to keep the session while the browser is open, but it is really under your control.
On the other side, if you are using OAuth to access some API (for example, if you are using the GMail API to check or send email from inside your web application), then yes, you will not be able to access the API after the token is expired, no matter how much activity was seen while the token was fresh. If you want to keep authorized you need something like a background process to keep renewing the tokens before they expire.

Related

Authenticating People API without UI

I want to authenticate personal google account for people API to send get/post requests,
However, I have to avoid authenticating for API each time as there will a cron job using the API. One way is to authenticate the first time and then use the refresh token for the necessary requests until the account revokes access (by changing password or manually removing the permission console)
Could there be a way, such that I could avoid manual authentication completely since the cron job will run on server-side
Used Service account for the same but didn't get required results
See https://developers.google.com/identity/protocols/oauth2/web-server
You can give your application consent once (the first time), and set in the authorization parameters the optional access_type='offline'.
"Set the value to offline if your application needs to refresh access tokens when the user is not present at the browser. This is the method of refreshing access tokens described later in this document. This value instructs the Google authorization server to return a refresh token and an access token the first time that your application exchanges an authorization code for tokens."

API Authentication for PWA

The Setup
We’re building a PWA (progressive web app). The main components are the app shell (SPA) and the API. The REST API will supply the data needed for the app, while the SPA will handle the rest (as per Google recommendation).
The Problem
Authentication of the end-user seems problematic because the web browser needs to be accounted for. We want the user login to persist through closing down the browser.
We’ve done the research about the possible ways of going about it, however we’d like to ensure that we’re not going in the wrong direction.
Solutions we’ve considered
Session based authentication - the user sends username and password to /accounts/auth and receives a HTTP only cookie with the session ID. The session needs to be stored in a database or Redis. The issue with this option is that cookies are automatically sent by the browser therefore we need a CSRF protection in place. Using the Synchronizer Token Pattern a new token would be generated every time a state changing request has been made e.g. POST. This means that the application needs to supply a CSRF token with every request so that the PWA can send it via AJAX. We determined that it’s not ideal as the user can send multiple post requests in a quick succession making some of them fail and resulting in a bad user experience.
We could also use this method without the CSRF by limiting the CORS policy to same domain and adding a header requirement which technically should stop all CSRF, however we're unsure how secure it would be.
JWT token based authentication - the user sends username and password to /accounts/auth and a new JWT token is issued. The JWT then needs to be stored in localstorage or a cookie. Using localstorage means that JWT is XSS vulnerable and if the token is stolen, an attacker can impersonate the user completely. Using cookies we will still have a CSRF issue to resolve. We considered a double submit cookie method but the CSRF would only refresh every time the JWT is reissued which creates a window for the attacker to find out what the CSRF is. It is not clear which method is best to use.
Session based authentication + JWT token authentication - the user sends username and password to /accounts/auth, a session is created, a HTTP only cookie is set in the browser and a JWT token is sent back to the user. The PWA can authenticate requests with the JWT and whenever the JWT expires the app calls /accounts/auth again to acquire a new one. The /accounts/auth endpoint would still need to be CSRF protected, however the impact of it on usability would be minimised.
There seems to be a large amount of articles claiming that localStorage is insecure and shouldn't be used so why are high profile organisations like Amazon still recommending it? https://github.com/aws/amazon-cognito-auth-js - this SDK uses localStorage to store the token.
You don't need to generate new CSRF token each time a client make a request. It's much easier to use a scheme like token = hash(id + secret + current_day). You only need to update it once a day, or even employ mixed scheme (if the token is invalid today, but is okay for the previous day, the server accepts the operation and returns new token in a predefined header for client to renew it). You may also use the cookie as an id, making the token totally stateless and much easier to check, no need to store them in the database.
Here is how I look at it.
JWT token authentication : with this approach, you can always use a time-bound token with its expiration set to say 2 hours or something?
Or another approach would also be to try and see how you could use some of the approaches the Credentials Management API suggests for example, auto-sign-in of users whenever they come back.
Stuff like 2-step verification with OTPs for instance; for very important features in your web app can be a choice. In this case basic stuff are tied to whichever one time authentication method you have.
Actually, you can also use user-defined pins or short codes (seen a lot in banking apps) to grant access to some features in your web app.
Hope this helps, or sparks some ideation.

How to use Google Identity to log in from multiple devices?

How can I use Google Identity platform as a login / registration system for my own service?
Specifically - how can I do this and support login for same user from different devices?
Using for web service, nodejs without npm modules: passportjs / googleapis / google-auth-library.
My idea:
User opens myClientApp/login page and clicks on GoogleLogIn button which will ask him to authorize my service for specific scopes of his Google account.
I then get the refresh token & access token and save it in DB, then send the refresh token to the client with cookie.
Whenever I make a call to my own service API I send the refresh token from the cookie.
As long as I have valid access token saved in my DB or the refresh token is not expired - I treat the user matching that refresh token as an active session for my service.
Security problems:
cookies attacks, and the refresh token is easily accessed from the browser. Could use https / encryption and more methods to secure the cookie and it's value. Still- someone could copy the cookie from one computer to another!
Multiple login problems:
If the user login on different device, a new refresh token will be created. The previous device the user logged in to will now hold a wrong refresh token in the cookie...
Could the OpenID solve this? Do I need to use JWT?
What is the most secure way to use Google Identity login in my own service while supporting multiple devices login for the same user?
First, make sure that you really understand the security implications for what you want to do.
For example, NEVER send the Refresh Token to a client.
If you want to use the same tokens for the same client on multiple devices, you have a chicken and egg situation. How do you "authenticate" the user at each device. How do you know that user "John" is actually user "John" but on a different device the first time?
Your goal is not to trade convenience for less security. Your goal should always be security first, no matter the inconvenience.
A better approach is to let Google authenticate and authorize a user on each device. They only have to do this once per device. Your backend systems keep track of the Refresh Token issued for each device. You can then generate the Access Tokens and Identity Tokens when needed - they expire after one hour anyways. Store a cookie on the user's device that identifies them to your system so that you can look up who they are, get the Refresh Token, create new Access Tokens, etc.
There is a limit to the number of Refresh Tokens that can be issued before the oldest ones are voided. I think the number is 50. This is usually not a problem. If a Refresh Token is invalid, just put the user back thru the authenticate process and store the new token.
Also provide the user with a sign-out method that removes all stored tokens in your system.
The cookie that you store on the client's devices should be opaque meaning that there is no stored information in the cookie and the cookie is only valid for that device and no other devices. This solves the stolen cookie moved to another device problem.
I will now touch on some of your questions:
My idea: User opens myClientApp/login page and clicks on GoogleLogIn
button which will ask him to authorize my service for specific scopes
of his Google account.
Google OAuth does not work that way. You send the user to a URL, Google manages all display and input with the end user. Once everything is complete a callback URL on your server is called and you are passed a code. The exact details depend on the type of OAuth Flow that you are using.
I then get the refresh token & access token and save it in DB, then
send the refresh token to the client with cookie.
During the OAuth Flow you will request the Access Token, Refresh Token and Identity Token. The Refresh Token is saved in the database. Never send this token to the client. Read my suggestion above about creating an opaque cookie that you send to the client.
Security problems: cookies attacks, and the refresh token is easily
accessed from the browser. Could use https / encryption and more
methods to secure the cookie and it's value. Still- someone could copy
the cookie from one computer to another!
Create an opaque cookie that is only valid for that device and no other devices. If a client sends you a cookie intended for a different device, consider this a problem and invalidate all cookies, tokens, etc for this user on all devices.
Multiple login problems: If the user login on different device, a new
refresh token will be created. The previous device the user logged in
to will now hold a wrong refresh token in the cookie...
I covered this issue above. Store the Refresh Token generated for each device in your DB. Consider each device / Refresh Token / cookie as a set.
Could the OpenID solve this? Do I need to use JWT? What is the most
secure way to use Google Identity login in my own service while
supporting multiple devices login for the same user?
By Open ID I think you mean Open ID Connect (OIDC). This is already integrated into Google OAuth and this is the part that generates the Identity Token.
Do I need to use JWT?
Google OAuth Tokens are generated from Signed JWTs. However for the most part you do not need to worry about the format of tokens. Google provides endpoints that validate and decode Google OAuth tokens.
What is the most secure way to use Google Identity login in my own
service while supporting multiple devices login for the same user?
I covered this question in the first part of my answer above.

Should OAuth 2.0 be used for Authentication Timeouts?

Developers of a mobile application are using the timeout period of OAuth 2.0 tokens to check when the application must re-authenticate with the server.
This conflicts with my understanding of the proper use of OAuth 2.0 tokens, although I am not exactly sure that I am correct.
My understanding:
OAuth is not about authentication but about authorization, e.g. can this device access some resource on a server on behalf of a user. Authentication logically precedes authorization and is about confirming the user is who they say they are.
So a user presents credentials (username and password) and the server authenticates that yes, this user is Bob.
The application Bob has logged into wants access to some resources on the server Bob has been authenticated to - say data from an API. So the application requests an OAuth token and it is granted, and one of its attributes is how long it exists. The application and the server exchange keys, and the data between the application and server is encrypted using the key.
An intruder reading the plaintext communication will not be able to decode it without the key. However, if an intruder is able to get the key they will be able to.
This is where the OAuth token end of life comes in. We don't want to use the same OAuth token (key) forever, because if an intruder was able to get that token they can decript our communication forever. If however, we refresh tokens every x hours, then they could decrepit the information only for x hours (let's say 2 hours).
I don't think the OAuth token expiration time should be connected with how long the user remains authenticated. That is simply up to the developers. In our case, if the user has some device security (a passcode for example), then we can let them remain authenticated for a long time (months for example). If they do not have device security then I want to force them to re-authenticate after a reasonable amount of time of inactivity, maybe 24 hours.
Is this correct or not, and if not, what parts.
Thanks in advance.
Bryan
Your understanding on OAuth 2.0 is correct. In very abstract manner, the protocol define a way to obtain tokens, which can be used by a client to communicate against a protected endpoint.
RFC6749 mandate the usage of TLS when communicating with authorization server (the token obtaining) as well as when using it against an API/protected endpoint (Bearer token usage as defined in RFC6750). This protects token from in-transit attacks.
The OAuth access token is recommended to have a short life time. This is to avoid token stealing as well as token misusing that can be done by client. You can read more about best practices from RFC6819. Access token lifetime specifics can be read from here.
Now about selecting the correct life time. As you already figured out, using a refresh token is the desired approach to renew access tokens instead of having a long lasting access tokens. For example, a refresh token can be valid for few days while access token valid only for few hours.
But be mindful about the following,
+ Whether your application can obtain and secure a refresh token
For example, SPA cannot obtain a refresh token as it cannot store it for extended time. In such case you need to look for alternative mechanisms to renew the access token.
+ Is access token used against external domain
Using access token toward an external API increase the threat vector. For example, if you have a closed system (client and backend in one domain) then you may think of increasing access token life time. But not for an extended period like 24hours.!
+ Single sign on (SSO)
Instead of using long lasting access tokens, you can get the help of authorization server to maintain an SSO behavior on top of browser. This is similar to "remember me" you observe in modern login dialogs. Once logged in, browser maintain a cookie which lasts for some time (ex:- A week). The next time you use OAuth token obtaining flow, your authorisations server detect this logged in state, hence skipping login dialog. Of course, such approach must be decided on exact security/policy requirements.
In conclusion, use access tokens with reduced life time.Using refresh token is the desired approach for token renewal. But depending on the situation, you can choose alternatives as well.

Separate authentication server for users and APIs

I'm working on a cloud service authentication system and I'm not entirely sure what the optimal way to handle authenticating requests is. We're planning to run our image server as a separate process from our API server so that we can scale them independently of each other. Handling request authentication with API keys is fairly simple, because we can just have the image server store its own API key and check that requests provide it in a header (over HTTPS obviously), same with the API server. For users though it gets more complex.
Right now we have it setup so that the API server will handle generating a session token and storing users in its database, however what we'd like to do is use 3 servers:
authentication server
API server
image server
and have the image and API servers authenticate requests against the authentication server. How exactly should this be done though? It seems like a bad idea performance-wise to hit the authentication server for every request that the API and image servers make. Can/should a token be verified from a different server than it was created on?
So for example: can/should I pass the token received from the authentication server to the image server, verify that the token came from "my.auth.server" and check that the user ID is the right one? Would JWTs be a good type of token for this?
Here's an alternative approach.
Your authentication issues a JWT token that is signed using a secret that is also available in your API and server images. The reason they need to be there too is that you will need to verify the tokens received to make sure you created them. The nice thing about JWTs is that their payload can hold claims as to what the user is authorised to access should different users have different access control levels.
That architecture renders authentication stateless: No need to store any tokens in a database unless you would like to handle token blacklisting (think banning users). Being stateless is crucial if you ever need to scale. That also frees up your API and image servers from having to call the authentication server at all as all the information they need for both authentication and authorisation are in the issued token.
Flow (no refresh tokens):
User authenticates with the authentication server (eg: POST /auth/login) and receives a JWT token generated and signed by the auth server.
User uses that token to talk to your API and image servers and assuming user is authorised), gets and posts the necessary resources.
There are a couple of issues here. Namely, that auth token in the wrong hands provides unlimited access to a malicious user to pretend they are the affected user and call your APIs indefinitely. To handle that, tokens have an expiry date and clients are forced to request new tokens whenever expiry happens. That expiry is part of the token's payload. But if tokens are short-lived, do we require users to authenticate with their usernames and password every time? No. We do not want to ask a user for their password every 30min to an hour, and we do not want to persist that password anywhere in the client. To get around that issue, we introduce the concept of refresh tokens. They are longer lived tokens that serve one purpose: act as a user's password, authenticate them to get a new token. Downside is that with this architecture your authentication server needs to persist these refresh token in a database to make them revokable before they expire (think "revoked" column in tokens table).
New flow (with refresh tokens):
User authenticates with the authentication server (eg: POST /auth/login) and receives a JWT token generated and signed by the auth server, alongside a long lived (eg: 6 months) refresh token that they store securely
Whenever the user needs to make an API request, the token's expiry is checked. Assuming it has not yet expired, user uses that token to talk to your API and image servers and assuming user is authorised), gets and posts the necessary resources.
If the token has indeed expired, there is a need to refresh your token, user calls authentication server (EG: POST / auth/token) and passes the securely stored refresh token. Response is a new access token issued.
Use that new token to talk to your API image servers.
OPTIONAL (banning users)
How do we ban users? Using that model there is no easy way to do so. Enhancement: Every persisted refresh token includes a blacklisted field and only issue new tokens if the refresh token isn't black listed.
Things to consider:
You may want to rotate refresh token. To do so, blacklist the refresh token each time your user needs a new access token. That way refresh tokens can only be used once. Downside you will end up with a lot more refresh tokens but that can easily be solved with a job that clears blacklisted refresh tokens (eg: once a day)
You may want to consider setting a maximum number of allowed refresh tokens issued per user (say 10 or 20) as you issue a new one every time they login (with username and password). This number depends on your flow, how many clients a user may use (web, mobile, etc) and other factors.
You can store some additional metadata (ip, geolocation, device, browser cookie, etc.) alongside refresh tokens. That way, you can be smart about when to reject malicious usages of refresh tokens in case it's compromised.
Common Q: Why store all refresh tokens, and not just revoked ones? You could do that. Ask yourself the following: Will I, at any point, need to have a functionality where I can dynamically revoke valid refresh tokens, based on some arbitrary, regulatory, legal, integrity, security etc. criteria? If so, the least you will need is a list of all issued tokens, plus any data required to implement the criterion logic. Example: Due to regulation, I need to ban all EU users equates to a delete from refresh_tokens were user_ip in <... eu logic ...>
one of the best ways to use is a JWT Token , you can generate and share it between all your servers and validate it on the server side .
https://jwt.io
also I think the best architecture to use in this case is the micro service architecture