I have a web application that uses "htps://mail.google.com/ email profile" endpoints/scopes for OAuth2 to integrate with Gmail's IMAP. According to the following news:
http://googleappsupdates.blogspot.ro/2015/12/increased-account-security-via-oauth2.html
https://support.google.com/a/answer/6328616
tokens will be revoked for certain applications on password change. The main use-case is to address the problem of lost or stolen mobile/desktop devices. This should not affect web applications otherwise it would ruin a big part of OAuth concept. But it is not clear from the news whether web applications will be affected or not. Could somebody clarify this please: Will OAuth2 automatic token revocation upon password change affect web applications?
Depends on how you are using OAuth 2.0.
If you have a Refresh Token, I am assuming, Google will no longer accept that token.
You application should detect that the Refresh Token is not valid and perform actions to allow the user to Authorize your application.
This may require you to notify the user out-of-band of OAuth as they may not be online at the time your Refresh Token fails.
Related
We are developing an application that uses a React front end website hosted on AWS using Amplify. This communicates with a .NET Core 3.1 Web API running on EC2 / Elastic Beanstalk. Cognito is used for user authentication with the Web API configured to use JWT tokens.
It works OK, but we have noticed that the Cognito provider stores the JWT access token in the browser local storage. This is what we see using F12 in Chrome and inspecting local storage.
From what we have read, storing access tokens in local storage is not advised as it makes the application susceptible to XSS attacks. Strange then, that the Cognito identity provider chooses to store sensitive information here.
If this approach is not considered safe, can the provider be configured to store this information elsewhere, such as cookies?
Alternatively, as we control both front and back ends, is there an alternative method that can be used to secure the API that does not involve tokens? Obviously the API needs to know which user is logged on to the web application in order to perform authorization checks. [Note authorization in the application is record level and defined in database tables, so it goes beyond simple user profile attributes.]
Many thanks in advance for your advice.
Doug
Security is a spectrum not a feature so it really depends on your appetite for risk vs effort. Amplify is not a particularly nice codebase, it has 500+ issues and if you look at the code you might be fairly shocked at the quality of it.
If you are using Hosted-UI then you can write code to manage the tokens yourself rather than using amplify, although you will need to learn a bit about OAuth grants and OIDC.
Be aware that the Hosted UI lacks a huge amount of features, so if you are going to use it make sure you are happy with it. Off the top of my head
no silent refresh capability in the hosted UI, so no safe way to store the refresh token.
no support for custom auth flow in the hosted UI
no passwordless support in the hosted UI
no ability to pre-populate a field in the hosted UI (e.g. username)
no ability to customise the plethora of obscure error messages in the custom UI
fixed now, but for years the email addresses were case sensitive!
An alternative is also to just use the AWS SDK to get tokens directly using cognito-idp but this also has a bunch of issues:
no code/PKCE/nonce capability so insecure in a mobile authsession
no ability to set oauth scopes, so can't use them
consequently not possible to use for OIDC
the SRP implementation is bananas and so far off spec
if you make device registration mandatory, it will deliver a working access tokens before the device is registered! (allows invisible devices for malicious logins)
We were using auth0 which was leagues ahead but we had to move to Cognito because of SMS OTP cost (min $25k per year at auth0).
I have been using AWS for over a decade now, Cognito is by far the worst service I have used, and I have used a lot! If you can avoid it, do so.
To answer the original question, yeah it's insecure. The best you can probably do is keep them in memory. If you wanted to you could probably put the hosted UI behind a cloudfront and use an lambda#edge to transform the token into a cookie instead. This has now opened you up to CSRF attacks though.
answering the original question: no, it is not safe at all.
Storing refreshtoken in any local storage accessable to any local app/script is not secure. So, the best way would be to store the refreshoten (and also the access token) in an httponly cookie or even better to store a one-time session token in httponly secure cookie could be used to get new access and refresh cookies - similarly as it is made by cognito hosted ui with XSRF-TOKEN.
See below how I would solve (and plan to solve) this issue:
Some background:
Due to GDPR regulations I think I can not use the cognito hosted ui - I have to make sure users read and accept the general terms and conditions (giving clear and auditable consent) and can review and accept cookie policies as well before they type in any user data for sign up. Nevertheless the built in hosted ui design is quite outdated and unflexible. I have an SPA website where I want to manage users, secure endpoints, etc.
So I have the following idea which is still not super secure but I think it is more secure one if you want to use js and ampify sdk and which also might answer your question:
I'll use amplify javascript sdk to let users sign up, change psw and log in (get tokenid, access token and refresh token), will make my own "hosted ui". I'll store the access token in memory only (not in local cookies and not in localstorage for sure). Access token will be used in header (bearer) to access apiGW endpoints. Access tokens will have very short expire dates. (I'd also use httponly secure cookies sent back by the apigw, as well as in the body.., then compare at BE side..)
And here comes the trick: I'd cut the refresh token into two. (Don't forget it is just a string.) I'd store the first part of the string in a local cookie (javascript can read it, if browser is closed and opened again it will be still there) and will send the other half of the refresh token to an apiGW endpoint (accessable without authentication) which will store it in a dynamoDB table (with TTL) and will send back an httponly secure cookie to the browser with a randomly generated "storagetoken" in it (which will be a key in dynamodb). There will be another unauthenticated apigw endpoint which will be called by the client whenever the client needs the full refresh token. Calling this endpoint the browser will send in the httponly secure cookie as well (same domain), so the backend will get it. As it is issued by the BE and available only in the given browser it can not be stolen so the backend will send back the stored half refreshtoken. The other half part of refreshtoken is stored in a simple cookie in the browser.
If the browser is closed and opened again client checks if there is any valid accesstoken and if not it checks if there is a half refeshtoken stored as cookie. Then ask the other part of refreshtoken assuming there is a httponlycookie also stored and it will get back the other part of the refreshtoken from the BE. In case of success the client tries to use the full refreshtoken to renew/get access token from cognito, in case of failure it will pop up the login screen.
Whenever refreshtoken is not in use it is deleted from the memory.
I know this is still not supersecure but might be a better solution than storing refresh token in localstorage.
Alternatively, as we control both front and back ends, is there an alternative method that can be used to secure the API that does not involve tokens?
I don't know anything of Amplify but in AWS Cognito what you describe is the Implicit grant OAuth flow. In AWS Cognito it is possible to use Authorization code grant where you instead of the token get a code which you in the backend can exchange for a user pool token.
https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-configuring-app-integration.html
I am using JWT and Spring security for user authentication and session management. It is working perfectly fine but I am worried what would I do if JWT will be compromised means I will use JWT of an user from some other system then I will able to access his/her previlages because JWT is not browser specific.
That's why, I want to make my JWT browser specific so that, now onw will able to login from same JWT using another machine.
I searched different way and I found one solution i.e. using cookies, we can differenciate the client browser but I don't think, it will be wise to use session cookies with JWT.
So, please guide me through this, how can I make JWT browser specific?
I am having difficulty understanding Hybrid flow with mobile application. I am using code id_token Hybrid flow provided by Identity Server 4 in .Net.
Here is my scenario.
All mobile request will go to backend server and backend server will forward request to different APIs on user behalf.
When user first time login
He will be redirected to identity server
A mobile web view will be opened
User will sign in using credentials
identity server will send Id Token and Access Code to Back end
Server
Back end Server will swap Access code for Id Token and Access Token
What token will be returned to mobile application to provide that user is valid. And is it responsibility of Back end server to get new access token without prompting user to re login until user sign out?
Is there any step wrong in above scenario ?
For mobile clients its recommended to use Authorisation code flow along with PKCE. Please read through these two answers to grasp some idea why its suggested Link-1 & Link-2.
Also, RFC8252 provide some best practices application for Native Apps (mobile clients are native apps.!). In that, it recommend not to use web-views.
here is a quote from RFC8252-overview
Previously, it was common for native apps to use embedded user-agents
(commonly implemented with web-views) for OAuth authorization
requests. That approach has many drawbacks, including the host app
being able to copy user credentials and cookies as well as the user
needing to authenticate from scratch in each app
By using web-view, you loose the true essence of OAuth 2.0. You client app get the ability to grasp end user credentials. So use the browser instead of web-view. (Please read more about embedded users agents from this link)
In your architecture, you could enable all of these, PKCE, Authorization code flow and usage of browser instead of web-view. But once the backed receives tokens, it should pass them to your client. That will be a challenge if you stick to this architecture.
But if you can make your mobile application to complete whole flow, you avoid that complexity. Once tokens are received, you may create a connection between backed server by validating tokens. Also, when tokens expire, mobile app will use refresh token to obtain new tokens.
Okay so this might be a very rookie-ish or naive question but I tried searching the internet and have resorted to stack overflow only after not finding anything fruitful. I have been reading about Token based authentication as well as Cookie based authentication. I have come across the opinion that token based authentication is better for Single page web applications but cannot clearly understand why. I will be using nodejs and angularjs to accomplish the same.
I guess that with Token based authentication as well as Cookie based authentication you mean Token authentication vs Session authentication because a token can be stored in a cookie
See this
With session based authentication the server maintains a sessions per each connected user. Client authenticates with its credentials and receives a session_id (which can be stored in a cookie) and attaches this to every subsequent outgoing request. So this could be considered a "token" as it is the equivalent of a set of credentials. This approach requires heavy server resources
Token based authentication is stateless and does not require server storage because the issued token (mainly JWT is used) contains the relevant user info and is signed with the server private key, so it is non-falsifiable. The token is stored in client side (cookie, localStorage, etc), attached to every request and validated by the server. Tokens are also suitable for REST APIs that do not require to maintain the state between each request
Forms based applications use session based authentication, and SPA often use token based authentication by the inherent advantages.
Note also that a SPA with session based authentication only will attach cookies to the outgoing request if the applicacion is located in the same domain that the server
SPAs tend to have many faces: the logged in view, the logged out view, or the restricted view. It’s all about access control. Your users are all getting the same app but they may not have the same levels of access. You’ll find yourself building access control logic for your front end and your back end.
Because tokens contain all this information, they are very portable: they can be used by your UI and your backend to make decisions. You can share them with partner services as a means of building Single Sign On services that delegate users to the correct application.
Hope this link will give you more information..
Token Based Authentication for Single Page Apps (SPAs)
This question has come up a lot but I haven't discovered the answer. I've read the OAUTH 2 spec and the separate security "considerations" document but I'm still fuzzy on something.
The circumstance is: RESTful based web services being accessed by mobile applications. I am both the server resource (creator and host of the RESTful services) and the authorization authority (I store the user's IDs and passwords and validate identity). Third party companies create the mobile applications that consume my services. I am using OAuth 2.0 to validate the user's UserID and Password and issue a token. TLS via https is used.
A nonce with a singed message is commonly used to prevent against replay attacks but as I understand it, that won't work in a mobile application because in order to sign a message, you need a shared secret. Any secret stored on a mobile app (that would allow you to sign messages) is no longer a secret. So a nonce can't be used.
So we have session tokens, which expire after some configurable period of time, and can be refreshed with a "refresh token".
My question is: If TLS is defeated (example: user is dumb enough to connect their mobile phone to a proxy server and install a certificate of the proxy, which then allows the proxy-server owner to read the unencrypted traffic), what prevents a hacker from replaying a request with a valid session token (while it's still alive), or worse, persisting the session for hours at a time using the refresh token to continuously obtain new session tokens?
The situation you suggest is one where the security is defeated and there is no security. The proxy can do things like steal the user's password during authentication or divert the access token to another application (either local or remote). You must just accept this scenario as a loss.
Also, it is typical for mobile apps to have a shared secret. As you point out, the secret loses some security being on the client, but it is still better than nothing. The secret is typically encrypted while at rest to prevent it from easily being stolen. Of course, the decryption key can be stolen from the app even when obfuscation techniques are applied to it but it provides some security.
Be sure to restrict the access rights of the secret on the client. Make sure that it is not configured for 2-legged auth. That should be saved for servers and only when needed.