I am using Keycloak to secure my react front-end and node.js back-end. These clients are protected using role based authorization.
My front-end application registered in Keycloak as a public client and back-end registered as bearer only client. When a user logging in to the front-end, i am taking the access token for that particular user and i am using that access token to call back-end api layer.
When user logout from the front-end i am clearing the front-end client session of that particular user from Keycloak by using keycloak object logout method. That is working fine and user is logging out and redirected to the Keycloak login page.
But the issue is i can still use the access token of that logged out user to call back-end api. The access token is still valid even though the user logged out.
I tried this end point to revoke the user access token. But didn't work
/auth/admin/realms//users/
Is there a way to revoke the access token of a particular user in Keycloak ?
I think you can only revoke sessions but not issued access tokens. So the only solution for this is to choose a very short access token life span in combination with silent refresh, so the usability is still good and the maximum access time after session revocation is equal or less than token life span.
EDIT: There is an official guide about how to handle compromised tokens. They do not mention how to revoke an individual access token, so there is no documented way to do so. However, you can revoke all issued access keys by the described "not_before" way.
It's possible at least on KC 17.0 via /protocol/openid-connect/revoke but since it's auth endpoint, you have to provide both the token and client_id, because the server must validate if the token belongs to that specific client that's calling.
This means that along with client_id, you may also need to send a client_secret or whatever other accepted of authenticating the client app to the server -- much like it was done earlier while obtaining the token on /protocol/openid-connect/token.
Also worth noting that the token must be passed as POST form param or GET query param of that name: token, and not as a bearer header/etc.
BTW. Refresh tokens can be revoked with the same /openid-connect/revoke endpoint in the same way as access tokens, while the older, easier to find /openid-connect/logout still only handles id tokens and refresh tokens (POST a client_id, client_secret etc, and also either refresh_token or id_token_hint to be killed) and still rejects any attempts with access token. At least on KC 17.0
BTW. I have no idea if /revoke can handle id tokens. I doubt it, but RFCs seem to allow that as custom extenstion. I have not tried with KeyCloak 17.0
You could call the following endpoint to revoke an access token using a post
{serverName}/auth/realms/{realmName}/protocol/openid-connect/revoke
Related
I would like to implement user login using JWT, but there is some confusion.
First, when the user successfully logs in, the server issues an Access Token and a Refresh Token. Then, The server sends the user information (id, name, grade) in the Access Token.
At this time, the Refresh Token is stored in the database along with the userId and is not delivered to the client.
The Access Token has a period of 7 days, and if client return within 3 days, authenticate the user through the existing Access Token.
If access token has been more than 3 days, server uses the user_id to query the Refresh Token stored in the database. At this time, if the Refresh Token is valid, server will try to reissue the 7-day Access Token.
I want to manage users in this way, is this correct?
I think the server should not pass the Refresh Token to the client.
I've read the following, but I do not know how to do it properly. Thank you for your advice.
OAuth 2.0 Access Tokens and Refresh Tokens
JWT refresh token flow
OAUTH2 Refresh Token
It sounds like you want to implement the full OAuth workflow for authentication. I'd advise you against the complexity unless your application really needs it. For a single API, it's alright if you issue a JWT token and pass it to the consumer, then the application will use this token in the requests and the server will authenticate the token.
However, if your application will be used by numerous devices (browser, mobile, Desktop, even other servers) and assuming you want extra security, then Oauth might pay off. In that case, you should give the refresh tokens to the user, and not auto-renew them. Otherwise, imagine someone steals someone else's (outdated) token... it will get auto-renewed! That person will gain access to the system on behalf of the other person.
I recommend you this package for working with express and Oauth: https://www.npmjs.com/package/express-oauth-server
Im building a REST services for existing product. Now to authenticate these, there needs to be some mechanism. To give specifications, I have a Db which stores userid and password . I have to authenticate using these credentials.
In above should I use OAuth or JWT? I prefer to use JWT to generate token first and pass token along every request.
Also From my understanding, I understand OAuth should be used when you have multiple consumers like games/apps using Facebook login. In my case, I don't have any have multiple consumers.
Please advise
Although it is true that OAuth is an authorization framework, it does help with JWT. JWT is a token specification, meaning, how you manage and issue tokens is largely left undefined. For instance, when your token reaches it's expiration, do you want your user to be abruptly logged out? By default, if you're using tokens with a certain duration, this will happen if you're checking for expired tokens, which you should be doing.
An OAuth Authentication server can serve the purpose of issuing an Access Token in JWT, and a Refresh Token. The access token will be included in every request, and the refresh token can be used when the access token is expired or about to expire to acquire a new access token. This is useful when taking into account the potential need to revoke a users access to your application. If you set a short access token life, then you'll be able to revoke access more quickly by removing their refresh token.
The technologies are different and not directly comparable because they solve different problems and are intended for different uses.
I would like to give the users a possibility to login with some external oauth2 provider (facebook) in my app. The client's part is running on mobile device in a native app.
I am not sure which of the approaches below should I prefer ?
Should the client send the user's access token by facebook with each request ? At each request backend asks facebook to validate the access token. Based on the validation's result, backend performs authorization and return corresponding result to the client.
Should the backend ask facebook to validate the access token only at user logon, then issue its own access token, return the access token back to the client and client will use this access token at making requests to the server to avoid contacting facebook at each request ?
I have read some questions about how to implement the auth with facebook and most of the devs are using B, but I haven't seen any explanation why is it good/bad to use A ?
What I see as benefits of the solutions:
backend doesn't need to care about issuing, refreshing, validating access tokens since this is done only by facebook's authorization servers.
this solution seems to be more effective, since it does not require to connect to facebook at each request.
Security tokens issued by Facebook are signed with a digital signature. The API server only needs access to the public key to validate the signature. There's no need at all to contact Facebook after the user authenticates.
A reason to issue your own tokens after the user signed in with Facebook could be to add claims to the token. But obviously having your own authorization server comes at a cost. It's up to you to weigh the pros and cons.
If you do decide to have your own authorization server, make sure not to write your own! There are open source options like Thinktecture IdentityServer.
I will vote for option B and here is my explanation,
Your API must authorise the request every time with some auth token , which cannot be external provider token, in such case anyone with an access token (eg: other developers) of other provider can access your api, basically there is no auth here.
When your sever issue access token, it's easy to validate and when needed could be revoked easily (eg: on password reset)
While authenticating , your server has fully control over issuing access token , so the validation is made only once and doesn't have to do every time while calling the API.
I'm writing an application with a front end in emberjs and backend/server-side in a nodejs server. I have emberjs configured so that a user can login/signup with an 3rd party Oauth (google, twitter, Facebook). I have a backend written in express nodejs server that hosts the RESTful APIs.
I do not have DB connected to emberjs and I don't think I should anyways since it's strictly client side code. I'm planning on using JWT for communicating between client side and server side. When a user logins with their oauth cred, I get a JSON object back from the provider with uid, name, login, access_token and other details.
I'm struggling with picking a strategy on how to handle user signup. There is no signup process since it's OAuth. So the flow is if the user is not in my db, create it. I do not support email/password authentication. What would be the flow when a user signs in with an OAuth provider for the first time? Should emberjs send all the details to the backend on every sign in so that backend can add new users to the db?
What should be part of my JWT body? I was thinking uid and provider supplied access token. One issue I can think of here is that provider specific access token can change. User can revoke the token from provider's site and signs up again with emberjs.
I'm open to writing the front-end in any other javascript client side framework if it makes it easier.
If we're talking about not only working but also secure stateless authentication you will need to consider proper strategy with both access and refresh tokens.
Access token is a token which provides an access to a protected resource.
Expiration here might be installed approximately in ~1 hour (depends on your considerations).
Refresh token is a special token which should be used to generate additional access token in case it was expired or user session has been updated. Obviously you need to make it long lived (in comparison with access token) and secure as much as possible.
Expiration here might be installed approximately in ~10 days or even more (also depends on your considerations).
FYI: Since refresh tokens are long lived, to make them really secure you might want to store them in your database (refresh token requests are performed rarely). In this way, let's say, even if your refresh token was hacked somehow and someone regenerated access/refresh tokens, of course you will loose permissions, but then you still can login to the system, since you know login/pass (in case you will use them later) or just by signing in via any social network.
Where to store these tokens?
There are basically 2 common places:
HTML5 Web Storage (localStorage/sessionStorage)
Good to go, but in the same time risky enough. Storage is accessible via javascript code on the same domain. That means in case you've got XSS, your tokens might be hacked. So by choosing this method you must take care and encode/escape all untrusted data. And even if you did it, I'm pretty sure you use some bunch of 3rd-party client-side modules and there is no guarantee any of them has some malicious code.
Also Web Storage does not enforce any secure standards during transfer. So you need to be sure JWT is sent over HTTPS and never HTTP.
Cookies
With specific HttpOnly option cookies are not accessible via javascript and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS.
However, cookies are vulnerable to a different type of attack: cross-site request forgery (CSRF).
In this case CSRF could be prevented by using some kind of synchronized token patterns. There is good implementation in AngularJS, in Security Considerations section.
An article you might want to follow.
To illustrate how it works in general:
Few words about JWT itself:
To make it clear there is really cool JWT Debugger from Auth0 guys.
There are 2 (sometimes 3) common claims types: public, private (and reserved).
An example of JWT body (payload, can be whatever you want):
{
name: "Dave Doe",
isAdmin: true,
providerToken: '...' // should be verified then separately
}
More information about JWT structure you will find here.
To answer the two specific questions that you posed:
What would be the flow when a user signs in with an OAuth provider for
the first time? Should emberjs send all the details to the backend on
every sign in so that backend can add new users to the db?
Whenever a user either signs up or logs in via oauth and your client receives a new access token back, I would upsert (update or insert) it into your users table (or collection) along with any new or updated information that you retrieved about the user from the oauth provider API. I suggest storing it directly on each users record to ensure the access token and associated profile information changes atomically. In general, I'd usually compose this into some sort of middleware that automatically performs these steps when a new token is present.
What should be part of my JWT body? I was thinking uid and provider
supplied access token. One issue I can think of here is that provider
specific access token can change. User can revoke the token from
provider's site and signs up again with emberjs.
The JWT body generally consists of the users claims. I personally see little benefit to storing the provider access token in the body of a JWT token since it would have few benefits to your client app (unless you are doing a lot of direct API calls from your client to their API, I prefer to do those calls server-side and send my app client back a normalized set of claims that adhere to my own interface). By writing your own claims interface, you will not have to work around the various differences present from multiple providers from your client app. An example of this would be coalescing Twitter and Facebook specific fields that are named differently in their APIs to common fields that you store on your user profile table, then embedding your local profile fields as claims in your JWT body to be interpreted by your client app. There is an added benefit to this that you will not be persisting any data that could leak in the future in an unencrypted JWT token.
Whether or not you are storing the oauth provider supplied access token within the JWT token body, you will need to grant a new JWT token every time the profile data changes (you can put in a mechanism to bypass issuing new JWT tokens if no profile updates occurred and the previous token is still good).
In addition to whatever profile fields you store as claims in the JWT token body, I would always define the standard JWT token body fields of:
{
iss: "https://YOUR_NAMESPACE",
sub: "{connection}|{user_id}",
aud: "YOUR_CLIENT_ID",
exp: 1372674336,
iat: 1372638336
}
For any OAuth workflow you should definitely use the passportjs library. You should also read the full documentation. It is easy to understand but I made the mistake of not reading the the whole thing the first time and struggled. It contains OAuth Authentication with over 300 Providers and Issuing Tokens.
Nevertheless, if you want to do it manually or want a basic understanding, here is the flow that I'd use:
Frontend has a login page listing Sign-in with Google/Facebook etc where OAuth is implemented.
Successful OAuth results in a uid, login, access_token etc. (JSON object)
You POST the JSON object to your /login/ route in your Node.js application. (Yes, you send the whole response regardless if it's a new or existing user. Sending extra data here is better than doing two requests)
The backend application reads the uid and the access_token. Ensure that the access_token is valid by following (https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken) or asking for user data from the provider using the access token. (This will fail for invalid access token since OAuth access tokens are generated on a per app/developer basis) Now, search your backend DB.
If the uid exists in the database, you update the user's access_token and expiresIn in the DB. (The access_token allows you to get more information from Facebook for that particular user and it provides access for a few hours usually.)
Else, you create a new user with uid, login etc info.
After updating the access_token or creating a new user, you send JWT token containing the uid. (Encode the jwt with a secret, this would ensure that it was sent by you and have not been tampered with. Checkout https://github.com/auth0/express-jwt)
On the frontend after the user has received the jwt from /login, save it to sessionStorage by sessionStorage.setItem('jwt', token);
On the frontend, also add the following:
if ($window.sessionStorage.token) {
xhr.setRequestHeader("Authorization", $window.sessionStorage.token);
}
This would ensure that if there is a jwt token, it is sent with every request.
On your Node.js app.js file, add
app.use(jwt({ secret: 'shhhhhhared-secret'}).unless({path: ['/login']}));
This would validate that jwt for anything in your path, ensuring that the user is logged-in, otherwise not allow access and redirect to the login page. The exception case here is /login since that's where you give both your new or unauthenticated users a JWT.
You can find more information on the Github URL on how to get the token and to find out which user's request you are currently serving.
I know there are already many posts about Oauth, Oauth2, JWT, etc.. I have read many and I more confused than ever so I am looking for some clarification. I will propose my view on the subject and I hope somebody can tell me if my implementation is secure enough or what I am doing wrong and how to improve it.
I am building an API Rest server for serving my resources to my users. Let's suppose it is a bank app where users can deposit, withdraw and transfer money.
I am using nodejs, hapijs, jsonwebtokens, and bcrypt for my server. I want to implement two token authentication flow (Oauth2).
This is the way I am doing it:
User logs in to the auth server by giving some credentials (username and password).
The server verifies the user's credentials, if they are valid, it will grant access to the user and return a refresh token and an access token.
These tokens are saved into the local storage of the browser or mobile device.
The access token:
is signed as a jsonwebtoken.
contains issued date, expiration date (5 min), user data (id, username).
The refresh token:
is signed as a jsonwebtoken and encrypted with bcrypt.
contains a unique identifier
may contain an expiration date
is saved in the database.
As long as the access token is valid, that means, it has not expired and contains valid user data, the resource server serves the user the requested resources.
When the access token is no longer valid, the auth server requests the client to provide a refresh token in order to issue a new access token
The server receives the refresh token from the user, decrypts it, compares it to the one in the database, checks if it has been revoked, and checks its unique identifier.
If the refresh token passes all tests, the server issues a new access token to the client.
If the refresh token fails one test, the server requests the user to re-authenticate.
Notes: I am trying to avoid the usage of cookies.
Questions:
If the user is able to steal an access token, I guess it can also steal the refresh token. So, how can I make the refresh token more secure?
Is my perspective of the Oauth2 flow correct?
What can I improve?
Am I missing something?
The reason OAuth2 is so confusion to many people is because it uses different authentication flows depending on what kind of client is used.
OAuth2 distinguishes two client type, confidential or public. Next to that, there are 2 grant flows that are redirection based (auth code and implicit) which are meant to be used with a browser or browser control.
The other two flows (resource owner password and client credentials) are meant to be used from non-browser apps (CLI, background services, trusted mobile clients).
I've described the different flows and when to use them in more detail in this answer here.