I am working on an eCommerce Website and an App. We use SAP Hybris for OAuth 2.0.
To get an access token I send a Cliend ID, Client secret, Username and Password to the auth server.
Problem Example:
If I log in with the App first and then the Website, I won't be able to refresh my token in one of the sessions.
The token I receive from the server is pretty standard and looks like this:
{
"access_token":"9T7IziRSIM_QIqFtttM8rhf83zU",
"token_type":"bearer",
"refresh_token":"MztkOmh67gIEiMwX5sED-Rug51c",
"expires_in":43199,
"scope":"basic"
}
The only difference is that in the "Website Token" the expires_in would have a lower value than 43199 since it was requested after the "App Token".
Since both the access_token as well as the refresh_token are identical, the moment one of them expire and we try to fetch a new token the first session that does it will receive completely different credentials. As soon as the second session (which is now expired) tries to also refresh it's credentials the server will deny new credentials since the old credentials can be used only once to get new tokens.
Every 12 hours the tokens become expired and the first client to request a new token effectively logs out the other client by doing so.
Question:
What could I do to deal with this problem?
I was thinking it should be possible to send a unique ID to my request to generate a unique token. However I cannot find any information about this on the SAP Docs.
Related
There is API on Laravel, which uses Laravel Passport for authentication. All worked well with the default settings. Then we decided to change the lifetime of the access token to 1 day and 1 month accordingly. It caused a problem with the refresh token.
Example: Access token is expired and the app sends the refresh token request to API. Then the app loses internet connection and can't get a new token. (Server sends new tokens but the app is unavailable). After the internet connection returned, the app sends a new refresh request but get 401. So apps need to get new code from API to authenticate the user. I don't think it's a good idea to force the user to login every day.
Any suggestions? Maybe there is some way like "handshake" to solve that problem? I mean refresh token only after confirmation the app got new tokens.
If I correctly understand your question, you're saying that you initially have an Access Token1, Refresh Token1 pair, and when the Access Token1 expired you try to request a new Access Token using the Refresh Token1.
Now, for some reason, you fail to receive this new Access Token2, Refresh Token2 pair, so what does the user do?. Well, you see this from the Consumer's point of view. If you see the same scenario from the Oauth2 Server's point of view.
The Server does not know if you failed to receive the token or you received it and failed to save. The server's job was to generate a new access token based on your valid refresh token. And as soon as it creates a new access token, it invalidates the old refresh token. This is the standard Oauth2 implementation.
You may try to make it so that the Old refresh token is not immediately revoked on new access token generation. But this introduces a possibility of replay attacks.
Hence, The standard practice is to have the User log-in again.
We have a web app in which we allow users to log into the app using any Open ID provider(e.g. Okta, Google, Facebook etc.). We want to implement the correct Open ID Connect prescribed methodology/workflow to keep the user logged into the site.
The existing implementation, looks at the expiry of the Access Token then if it's close to expiry uses a Refresh Token to get a new Access Token to keep the user logged in. I feel like this is wrong. When a user logs in to the web app, the Identity Token is used to Authenticate the identity of the user using the Authorization Code workflow. The Access Token and Refresh Token are stored on the server side. Periodically, the Refresh Token is used to get new Access Tokens to keep the user logged into the site. I believe this is a security risk because -
Imagine if a user is logged onto his OP account in a browser. He opens up Sky and is directly logged into MP because he’s already logged into MP. He then in a separate tab, logs out of his OP account. He will continue to be logged into MP for days on the basis of this Refresh Token/Access Token mechanism! Isn’t this a security risk?
If feel like the correct way to go about this is to use Session Management using iframes as prescribed here on OIDC -
https://openid.net/specs/openid-connect-session-1_0.html
For more context, when a user logs into our WebApp we pull data from the OP's UserInfo endpoint to create a profile within our WebApp and set permissions/roles within our app based on data sent over from the OP's UserInfo endpoint. We continue doing this periodically. For this purpose, I feel like using the Access Token(and using the Refresh Token to get new Access Token) to access the UserInfo API is correct because it conforms to the OAuth 2.0 concept of protecting/authorizing API/Resource endpoints using Access Tokens.
I want to know if this is indeed the correct way to manage how a user should be logged in when supporting Open ID Connect.
I think the first question is whether you want to bind the lifetime of an OpenID Connect provider Single Sign On session with the session of your application. You just want to authenticate a user using their OpenID Connect service. If I logout of Google, I expect to be logged out of GMail, but not a third-party application that used Google for authentication. Would you like to implement Single Sign Out as well?
But if I wanted to be logged out when you logout of the OpenID Connect provider, I would implement the OpenID Connect Session management. There is one thing good to be aware of when using iframes and cookies - browsers have an option to "Block third-party cookies" (that's how Chrome calls it), it's turned off by default, but as far as I know, it disables the SSO functionality when turned on.
I'm not sure why you request the userinfo endpoint periodically. If you just want to check whether the access token is still valid, you could also use the token introspection endpoint.
For security concerns, I would suggest you to read the OAuth 2.0 for Browser-Based Apps RFC. It recommends using the auth code flow with PKCE instead of the implicit flow. With the implicit flow, access tokens transported in redirect URLs stay in network and browser caches and can be used right away by an attacker. The auth code with PKCE needs a code_verifier (one-time secret) in order to be exchanged for tokens. So I would first check how the providers work with a configuration you choose and if it's even supported.
We have a restful API developed on spring-boot V1.5.7 and it is secured by OAuth with "password" grant type. We are using only access token, the refresh token is not being used. The validity of access token is set to 15 mins. Initially, we hit the token endpoint and get the token and consuming the services. Though the services are being consumed very frequently the access token is getting expired after 15 mins. What we are expected to do is, when the services are not being called for 15 mins only then the token should be expired.
Can anyone please help me on this?
Looks, First we need to know Why we used access token?
Access token is used for accessing protected resource. It has a validity periods say for example 1min, 10min etc. After that time, token becomes invalid. To get a new valid token you should use refresh token.Though you can get a completely new token using your username and password. Even if you invoke any api within the expiry time though, the token invalid after the expiry time. If you don't invoke any api within the expiry time, token becomes also invalid. This is expected behavior.
Why this is expected?
Suppose you get an access token from server and access protected resource from server with access token. Somehow man in the middle get the token by sniffing packet. Then intruders can get easily access the resource as you can and as much time he want's. So technically we can say that, your account is being hacked.
To prevent this attack, you should define a token validity periods that would be suit for your use case. So this is more secure than previous.
I would strongly recommended that allow refresh token for your system.
However You can also configure your system to reuse the token. This link may be a help.
You can use OauthRestTemplate (if you don't want to write your own logic) which will fetch a new the access token (using refresh token) after it is expired. There is no reason to not use refresh token if you are planning on using OAuth in your application.
I am quite new to JWT based authentication. And im quite confused about the refresh token mechanism. In my case, I have designed my application as,
1. User will login to the application, and when the login is successful then it will go to the authentication server and sign a jwt and will pass it to the client.
2. And then the client will store the refresh token and the short lived token in the local storage
3. Once the resource server is called the token will be sent through the header. and will get validated.
My question is, in which point should we request another token using the refresh token mechanism. Should we check whether the short lived token is invlaid before sending the request to the resource server. or should we get a new token once the validation fails in resource server? or is there any better way to handle this?
A Refresh Token is a special kind of token that can be used to obtain a renewed access token —that allows accessing a protected resource— at any time.
Although Access Tokens can be renewed at any time using Refresh Tokens, they should be renewed when old ones have expired, or when getting access to a new resource for the first time. Refresh Tokens never expire OR have very long expiration time.
I trying to implement a token based authentication approach:
Every successful login creates new token.
If user selects "keep me logged in" or the user is using a mobile device, the token is persisted in a Redis database without an expiration date. Otherwise, the token will expire in 20 minutes.
Once user is authenticated, the token is checked from each subsequent request in my Redis database.
I'm wondering how I can identify devices. In case of mobile devices, I can use a device identifier. But how can I identify a browser?
Example: The user logs in using Chrome and selects "keep me logged in". A token is generated and persisted with the browser name in Redis. If the user logs in from Firefox, saves the token and "Firefox" in the database. I save the token in Redis whereas token is created on successful authentication. Is it fine to persist only the token and the browser where the token is being used? Or do I need to persist the IP as well?
Additional question: How to avoid attackers to steal the token from a cookie?
How token-based authentication works
In a few words, an authentication scheme based on tokens follow these steps:
The client sends their credentials (username and password) to the server.
The server authenticates the credentials and generates a token.
The server stores the previously generated token in some storage along with the user identifier and an expiration date.
The server sends the generated token to the client.
In every request, the client sends the token to the server.
The server, in each request, extracts the token from the incoming request. With the token, the server looks up the user details to perform authentication and authorization.
If the token is valid, the server accepts the request.
If the token is invalid, the server refuses the request.
The server can provide an endpoint to refresh tokens.
How to send credentials to the server
In a REST applications, each request from client to server must contain all the necessary information to be understood by the server. With it, you are not depending on any session context stored on the server and you do not break the stateless constraint of the REST architecture defined by Roy T. Fielding in his dissertation:
5.1.3 Stateless
[...] each request from client to server must contain all of the information necessary to understand the request, and cannot take advantage of any stored context on the server. Session state is therefore kept entirely on the client. [...]
When accessing protected resources that require authentication, each request must contain all necessary data to be properly authenticated/authorized. It means the authentication will be performed for each request.
Have a look at this quote from the RFC 7235 regarding considerations for new authentication schemes:
5.1.2. Considerations for New Authentication Schemes
There are certain aspects of the HTTP Authentication Framework that
put constraints on how new authentication schemes can work:
HTTP authentication is presumed to be stateless: all of the
information necessary to authenticate a request MUST be provided
in the request, rather than be dependent on the server remembering
prior requests. [...]
And authentication data (credentials) should belong to the standard HTTP Authorization header. From the RFC 7235:
4.2. Authorization
The Authorization header field allows a user agent to authenticate
itself with an origin server -- usually, but not necessarily, after
receiving a 401 (Unauthorized) response. Its value consists of
credentials containing the authentication information of the user
agent for the realm of the resource being requested.
Authorization = credentials
[...]
Please note that the name of this HTTP header is unfortunate because it carries authentication data instead of authorization. Anyways, this is the standard header for sending credentials.
When performing a token based authentication, tokens are your credentials. In this approach, your hard credentials (username and password) are exchanged for a token that is sent in each request.
What a token looks like
An authentication token is a piece of data generated by the server which identifies a user. Basically, tokens can be opaque (which reveals no details other than the value itself, like a random string) or can be self-contained (like JSON Web Token):
Random string: A token can be issued by generating a random string and persisting it to a database with an expiration date and with a user identifier associated to it.
JSON Web Token (JWT): Defined by the RFC 7519, it's a standard method for representing claims securely between two parties. JWT is a self-contained token and enables you to store a user identifier, an expiration date and whatever you want (but don't store passwords) in a payload, which is a JSON encoded as Base64. The payload can be read by the client and the integrity of the token can be easily checked by verifying its signature on the server. You won't need to persist JWT tokens if you don't need to track them. Althought, by persisting the tokens, you will have the possibility of invalidating and revoking the access of them. To keep the track of JWT tokens, instead of persisting the whole token, you could persist the token identifier (the jti claim) and some metadata (the user you issued the token for, the expiration date, etc) if you need. To find some great resources to work with JWT, have a look at http://jwt.io.
Tip: Always consider removing old tokens in order to prevent your database from growing indefinitely.
How to accept a token
You should never accept expired tokens or tokens which were not issued by your application. If you are using JWT, you must check the token signature.
Please note, once you issue a token and give it to your client, you have no control over what the client will do with the token. No control. Seriously.
It's a common practice to check the User-Agent header field to tell which browser is being used to access your API. However, it's worth mention that HTTP headers can be easily spoofed and you should never trust your client. Browsers don't have unique identifier, but you can get a good level of fingerprinting if you want.
I don't know about your security requirements, but you always can try the following in your server to enhance the security of your API:
Check which browser the user was using when the token was issued. If the browser is different in the following requests, just refuse the token.
Get the client remote address (that is, the client IP address) when the token was issued and use a third party API to lookup the client location. If the following requests comes an address from other country, for example, refuse the token. To lookup the location by IP address, you can try free APIs such as MaxMind GeoLite2 or IPInfoDB. Mind that hitting a third party API for each request your API receives is not a good idea and can cause a severe damage to the performance. But you can minimize the impact with a cache, by storing the client remote address and its location. There are a few cache engines available nowadays. To mention a few: Guava, Infinispan, Ehcache and Spring.
When sending sensitive data over the wire, your best friend is HTTPS and it protects your application against the man-in-the-middle attack.
By the way, have I mentioned you should never trust your client?
Once server is receives the request from the client, it contains the User-Agent. This attribute will help us to identify the client.
Please refer this link: How do I detect what browser is used to access my site?