I'm currently using auth0-js library v8 to authenticate users against Auth0. This library forcibly signs JWT tokens using RS256. Temporarily, I would like to decode the token and re-encode it using HS256/my current CLIENT SECRET, before returning the token in the authenticated response. Can I use Auth0 rules for that? Any idea how?
Reacting to Pawel's comment up there: this is no longer an issue! With Graphcool resolvers you can now extend your schema to handle authentication (amongst others) whatever way you deem suitable.
Related
I'm looking for some clarity regarding security concerns with just JWT in our current project.
basically it is working right now like this:
User authenticates with username + password at an authentication Service
frontend gets JWT
frontend can use this JWT in the communication with the backend.
but that seems unsecure for many reasons, so we discussed this so far and had a few ideas to make it more secure:
additionally encrypt the JWT, basically make an nested JWT (JWE) and work with a blacklist on logout... but here the question remains why work with an JWT and not a stateful authentication like Shared Sessions and a Redis service
Implementing an Api-Gateway so that the frontend or User gets a Session cookie and the gateway works with JWT for backend and auth. unfortunatly i've found no implementation like this whatsoever
We just want to be kinda secure in Login/Logout AND be scaleable in the the future so that there might be X other backends.
apologies for any errors, english is not my first language and i'm happy to answer any questions regarding this.
take care.
You are right that keeping tokens on the front end has some security issues. The current best practice is to try to keep tokens out of the browser altogether. At Curity we have described one possible solution as the Token Handler pattern. It adds a bit more complexity to your system but enables you to use secure sessions on the front instead of any tokens. We have provided a few implementations of the components needed by the Token Handler, you can have a look at how to run our complete example here: https://curity.io/resources/learn/token-handler-spa-example/
As to your first idea, if you want to implement blacklisting tokens, then you're in fact implementing sessions, and you're better off with cookies and plain old HTTP sessions. JWEs protect the contents of your token but an attacker can still steal such a token and use it to call your APIs.
We would like to have users authenticate to a Slack app by providing their current Keycloak JWT as a one-time authentication procedure. This would allow us to associate their Slack user ID with their Keycloak user ID.
However, I can't find any endpoint like AWS' GetCallerIdentity within Keycloak. I have combed the docs, and the closest thing I can find is an identity token mentioned here. However, I can't find anything about how to unravel that identity token to securely gain information about its owner.
Can anyone point me in the right direction?
Thank you!
Open ID Connect defines userinfo endpoint, which is similar to AWS GetCallerIdentity endpoint. But that requires to fire request. I would prefer to read user details from the token.
Standard JWT (OIDC) libraries support token decoding. Access/ID token has 3 parts: header, payload, signature. You can use base64 decode on the payload part and you will get json with user details. Of course proper implementation will read also header to get used algorithm and it will validates token signature with used IdP public key and algorithm. Otherwise someone can tamper token.
https://jwt.io/#debugger-io provides nice visual interface, which will help you to understand and also decode token structure:
Keep in mind: what is returned in the userinfo response depends on OIDC client configuration in the Keycloak
I am developing a REST application with its own authentication and authorization mechanism. I want to use JSON Web Tokens for authentication. Is the following a valid and safe implementation?
A REST API will be developed to accept username and password and do the authentication. The HTTP method to be used is POST so that there is no caching. Also, there will be SSL for security at the time of transit
At the time of authentication, two JWTs will be created - access token and refresh token. Refresh token will have longer validity. Both the tokens will be written in cookies, so that they are sent in every subsequent requests
On every REST API call, the tokens will be retrieved from the HTTP header. If the access token is not expired, check the privileges of the user and allow access accordingly. If the access token is expired but the refresh token is valid, recreate new access token and refresh token with new expiry dates (do all necessary checks to ensure that the user rights to authenticate are not revoked) and sent back through Cookies
Provide a logout REST API that will reset the cookie and hence subsequent API calls will be rejected until login is done.
My understanding of refresh token here is:
Due to the presence of refresh token, we can keep shorter validity period for access token and check frequently (at the expiry of access token) that the user is still authorized to login.
Please correct me if I am wrong.
A REST API will be developed to accept username and password and do
the authentication. The HTTP method to be used is POST so that there
is no caching. Also, there will be SSL for security at the time of
transit
This is the way most do it, so you're good here.
At the time of authentication, two JWTs will be created - access token
and refresh token. Refresh token will have longer validity. Both the
tokens will be written in cookies so that they are sent in every
subsequent requests
Storing the tokens in cookies I not dangerous in itself, but if you somehow get you JWT module on your server to read them from there you vulnerable to CSRF attacks where any webpage can trigger a users browser to send a form + you sites cookie to your server unless you use CSRF tokens. So generally they are stored in localStorage and "manually" added to request headers every time.
On every REST API call, the tokens will be retrieved from the HTTP
header. If the access token is not expired, check the privileges of
the user and allow access accordingly. If the access token is expired
but the refresh token is valid, recreate new access token and refresh
token with new expiry dates (do all necessary checks to ensure that
the user rights to authenticate are not revoked) and sent back through
Cookies
Apart from the cookie dangers, it seems safe.
Provide a logout REST API that will reset the cookie and hence
subsequent API calls will be rejected until login is done.
You don't even need to make an API call, you can simply just purge the cookies or the localStorage object and make sure your client doesn't break on missing tokens.
The standard for the express-jwt module expects the tokens to be in its own "Authorization: Bearer [Token]" header, which I would strongly recommend over cookies. The localStorage API is available all the way back to IE8 so you should be good.
Edit:
First, it's important to know the difference between XSS and CSRF attacks since they're often believed to be the same thing.
XSS is when users get unsafe JS running on your domain in other users browsers when that happens neither JWT in localStorage or sessions and JWT in cookies are safe. With httpOnly flag on cookies, you can't directly access them, but the browser will still send them with AJAX requests to your server. If this happens you generally out of luck. To prevent this, make sure to escape all user input if it's sent to the browser.
If you load 3rd party JS with script tags or iframes this might compromise localStorage unless you are careful, but I haven't worked enough with this to help you here.
CSRF is only when other domains are trying to send normal HTML forms to your server by getting the browser to send cookies automatically. Frameworks prevent this by inserting unique random strings as hidden fields and checking them again when it's submitted. JWT's in localStorage is safe from this since each domain gets its own separate localStorage area.
But ultimately all this depends on if your service will be using one single domain, in which case httpOnly cookies will be plenty secure and easier to set up, but if you wanna spread your service out on multiple domains like api.domain.com + app.domain.com or add a native app you're forced to store you're JWTs in localStorage or some other native storage area.
Hope this helps!
I asked this question two years back and also accepted the answer. However, based on my experience and study in the last two years, I'd like to answer this just in case someone stumbles on this thread with the same question.
The approach mentioned in the question is similar to the "Resource Owner Password Credentials" grant type of OAuth 2.0. However, I think it is better to use the "Authorization Code Grant" type instead and Cookie to store the tokens instead of browser localStorage or sessionStorage. I have detailed my reasons, implementation points, security considerations and references in this StackOverlow answer.
Like OP I been using resource owner password grant.
I learned so much from Saptarshi Basu's other answer in a different post I think anyone looking into OAuth Code Flow should take a look at it, it has outlined a very solid approach to auth SPA and resource servers. It primarily relies on your backend(resource server) to handle authentication with the auth provider as a private client.
However, I will just add that people looking at implementing authentication with SPA should also consider OAuth Code Flow with PKCE. The main goal of PKCE is to allow public client such as SPA to authenticate directly with auth provider. All PKCE adds, is that when a SPA app initiates authentication, a hashed value is sent to the auth provider when the user is authenticated. And after user authenticate with the authorization provider, it redirects the user back to SPA with that hashed value as well as authorization code. Now, for the next part where the SPA calls auth provider to exchange code for tokens, instead of providing client secret, it has to provide the key that was originally used to create the hashed value. This mechanism guarantees the code cannot be used by someone who intercepted the code, and the SPA doesnt need to store a client secret like a server-side app does.
Now the only thing I'm not certain at this point is which is technically more secure, server-side authentication using standard Code Flow without PKCE or SPA authenticating directly using PKCE? Most resources I could find online currently describes and recommends the latter . However I feel that letting a private server side client handle authentication (as Saptarshi Basu described) might still be more secure. I would love to hear his opinion on this as well.
My understanding of refresh token here is:
Due to the presence of refresh token, we can keep shorter validity period for access token and check frequently (at the expiry of access token) that the user is still authorized to login.
Please correct me if I am wrong.
Assuming you're talking about using JWT as Bearer-token in OAuth (and I would strongly advice to follow the OAuth 2.0 protocol), that's right.
With an additional auth-time (timestamp of authentication) claim in your JWT, you could even drop the second token and sent your access- as a refresh-token (the auth-server could then issue a new access-token if token is valid & auth-time within allowed range)... but sure, it's also good to follow the standard ;)
Anyway, there are certain additional aspects (that tend to get difficult or are even against the fundamental ideas of JWT) you should consider before using JWTs as refresh-token, as this basically means you introduce long-living JWT:
do you need to have something like forced user logout/ token revocation by subject (e.g. if user got identified as fraudulent)?
do you need to have something like revocation of a specific token (e.g. if a user looses a device)?
...
Dependent on your use-case you should consider all the possible implications, long-living tokens have as they usually require you to introduce some kind of state on your server-side (e.g. to allow revocation/ blacklisting). Keep in mind the beauty and security of the JWT concept lies within JWTs being short-lived.
If we get token from the rest server and use AuthorizationToken header in every request for authorization, we still need to keep it when the browser's page is closed.
The only universal way to do it is to put the token to cookies. But in such way even if the cookies are not used for authentication, they can be stolen by XSS.
And we can't use httpOnly flag. So:
Are there any other specific ways to protect the token and keep it safe?
If HTTPS is used during the whole session and the cookies with token were stolen, is it possible to hijack the https session with a token?
My answer is perhaps a bit naive but why not store the token in the persistence storage of your browser. If you use Angular, with code as describe below:
function((...), $window) {
(...)
$window.sessionStorage['userToken'] = '<user-token>';
}
I don't really see other approaches (exception cookies) to keep such hints when the browser's page is closed.
The problem with cookies is that your client needs to be a browser to leverage this feature transparently... Moreover it's really not the better approach for authentication within RESTful services ;-)
You can combine this with a mechanism of security tokens with an expiration date and the ability to refresh them, as described in the following link: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/.
In addition, you can use JS framework like Angular that provides solutions to XSS. See the following links for example:
http://java.dzone.com/articles/angularjs-how-handle-xss
angularjs + cross-site scripting preventing
Hope it provides some hints to your issue,
Thierry
We would like to implement "Sign-in with LinkedIn" in our app. Since the app has JS fronted and RESt-based backend, we decided to exchange JSAPI tokens for REST API OAuth tokens as described here.
If a user successfully signs in, the frontend sends credentials cookie with client-side bearer token and member ID to the backend. On the backend we check if a user with such a member ID already exists and if not, we exchange JSAPI token for REST API OAuth token, retrieve user details from LinkedIn a store it in our database.
Now the question is if we can use that cookie to authenticate each user's request to our REST backend. After a user successfully signed in via JSAPI, the cookie should be automatically passed to our backend on all subsequent requests so we can check member ID. Are there any drawbacks that we missed? Or is this idea as a whole wrong?
Should we rather authenticate a user only once by means of the cookie and then issue our own authentication token and send it back to the client?
The way cookies work in general is they are passed on every request to the domain they belong to. LinkedIn is setting a credentials cookie to your domain.
As long as you are validating those credentials on every request it's perfectly acceptable to use their tokens as authentication.
Personally I don't find that to be a great idea and would prefer to validate their credentials once and create my own auth token to use from there on out. You can always set that token to expire at some-point and re-validate the LinkedIn credentials (which will still be getting sent on every request anyway). This limits the amount of times you're checking with LinkedIn and should increase the responsiveness of your app.
Either way could work.
If you are using the LinkedIn cookie to validate a user by member id, you should validate the cookie's signature on each request per section 2 of the doc you linked and question 2 of the FAQ.
Using your own token could make it easier to implement an account which belongs to your app and is not necessarily connected to LinkedIn, assuming there's the potential to either connect solely with some other service(s) or no 3rd part(y/ies). Still should validate any time you trust the member id in the cookie though.
The doc provides a validation example in PHP, and if you're interested in improving a ruby version, I have a shameless plug.
The flow that you've outlined in your latest comment of going straight for the OAuth tokens is the best way to go if you were only signing in to convert the JSAPI tokens to OAuth tokens and then not using the JSAPI further. If you were planning to actually use both the JSAPI tokens within your front-end app and the OAuth tokens on your back-end, then it's better to take the conversion route.