JWT terminology has been bothering me for a few reasons. Is JWT suitable for Authorization or is it only for Authentication?
Correct me if I'm wrong but I have always read Authorization as being the act of allowing someone access to a resource yet JWT doesn't seem to have any implementation that actually allows access to users to a given resource. All JWT implementations talk about is providing a user a token. This token is then passed with every call to a back-end service endpoint where it is checked for validity and if valid access is granted. So we can use JWT for Authentication of any user but how can we restrict the access to particular valid users ?
How can we use JWT for restricting a few users depending on roles they have?
Do JWT provide any type of Authorization details as well or does it just provide us Authentication ?
Thanks in advance for your help and reading my doubt patiently.
Authorization with JWT can be achieved using the token specific claims.
As many other user information packaged as claims in the Json Web Token the specific permissions can be pre-filled in the token and can be intercepted later on by an authorization service.
Typically the authorization would be permission based where permissions are used to restrict access to an api endpoint (may also be used to grant users access to views on the frontend apps).
Here down a sample JWT token having a permission element:
{
"UserInfo": {
"id": "#{USER_ID}",
"roles": {
"#{ROLE_NAME}": "#{ROLE_ID}"
},
"permissions": {
"#{PERMISSION_NAME}": "#{PERMISSION_ID}",
}
},
"exp": 1488888888
}
JWT can be used for two purpose:
Authentication (as you said)
Information Exchange.
The second part is the interesting one. A JWT contains:
a header: contains algorithm and token type
a payload: Which are statements about an entity (typically, the user) and additional metadata. There are three types of claims: registered, public, and private claims.
a signature: The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn't changed along the way.
The payload can contains information about a user such as a list of rights.
This way you can use it for Authorization.
Example from jwt.io:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
which contains:
{
"alg": "HS256",
"typ": "JWT"
}
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
you can see that the payload contains the identity and information about the administration right. You can trust theses data because of the payload signature.
User logins first. Once user pass the login process, or we say once user is authenticated, you sign a jwt token and send it to the user. this is node.js snippet
async postLogin(req, res, next) {
// parse the req.body, get the email,password
// check if the email exist, if exists check the passord
// now you are sure credentials are true, create the jwt.
const token = jwt.sign({ _id: this._id, email: this.email }, "this-is-secret", {
expiresIn: "1h",
res
.status(200)
.header("x-auth-token", token)
.json({ token, userId: existingUser._id.toString() });
});
}
now client will takes it save it to localStorage. (for simplicity i m using localStorage). IN the client side, user sends post request to login and gets what I sent above. It will take the token, and save it. since it is async request, it will be like this. this is a little react code to demonstrate:
.then(resData => {
localStorage.setItem('token', resData.token);
localStorage.setItem('userId', resData.userId);
One thing about tokens, browser does not send it automatically, so client will manually attach it to the request.
fetch(url, {
method: "post",
headers: {
Authorization: 'Bearer ' + localStorage.getItem('token')
}
})
Once your server gets the request, you check the incoming token, if it is a valid token you will authorize the user to access certain routes or services. So user will be Authorized.
Authentication is the process of identifying users and validating who they claim to be. One of the most common and obvious factors to authenticate identity is a password. If the user name matches the password credential, it means the identity is valid, and the system grants access to the user, so we say user is authenticated
Is JWT suitable for Authorization or is it only for Authentication?
The answer to this question is lying in the following lines of RFC7519 Standard:
JSON Web Token (JWT) is a compact claims representation format
intended for space constrained environments such as HTTP
Authorization headers and URI query parameters.
JWT doesn't seem to have any implementation that actually allows access to users to a given resource.
I would say this part of your understanding needs a bit of polishing ;-)
Indeed JWT has a structure called Claims and there you can find topics related to authorization.
The remaining part of your understanding is not following a correct sequence. In fact, there is a missing piece called Token Issuer. This guy is responsible to Authenticate JWT token requester and issue a JWT token if and only if the authentication process was successful and the requester was authorized. Then the issued JWT token could be verified by checking the signature, meaning that, the token that has been issued via a token issuer like an Identity Server will contain a hash code of message which will allow the consumer of the token to double-check the signature (hash code) to make sure the token has not been modified via unauthorized access during the transitions between client-server. Then if the token was a valid token the consumer at the next step can extract token (JWT) claims to process the authorization part.
Related
Can JWT authentication support multiple APIs.So the users will have the same username/password for the multiple APIs and can login to multiple APIs simultaneously using the same token.
I did a lot of research but still could not find anything relevant.
Definitely yes.
One of the main strengths of JWT tokens is that they do not require a central authentication authority, as long as each token can be verified (i.e. the API holds the required keys to verify the signature). So each API can verify the authenticity of the token, which in turn holds the authorization data, without any modification (other than verifying the JWT token).
In a multi-API (multi principal) setup, there would be a token issuance service (which handles authentication requests by verifying credentials and issuing tokens). Then, each principal can accept/verify these tokens without knowing anything about the credentials.
Further more, you can use aud (Audience) field to discriminate API usage. An API , after verifying the JWT, can examine the aud field and only accept the token if it can identify itself in the aud data. Check this wikipedia article for more info
I have an application which needs to implement oauth 2 for securing rest API. The simple flow will be when a user logs in they should have access to some protected resources ( as per their role).
I will be using angular 7 as front end.
as per this diagram I need to use implicit grant for Single Page Applications.
now i went on to search and found https://www.devglan.com/spring-security/spring-boot-oauth2-angular
API Name - Login
Method - POST
URL - oauth/login
Header - 'Authorization': 'Basic ' + btoa('devglan-client:devglan-secret')
Body - {'username' :'admin ',
'password' :'admin',
'grant_type': 'password' }
Content-type: application/x-www-form-urlencoded
Now my only concern in this approach is.
i. why this client id and client secret are revealed in angular code ? is client secret not supposed to be kept secret ?
We don't need any secret key to implement the implicit grant flow in the js applications.
You can see the following http url sample which needs few things such as client_id, redirect_uri etc.
We will get the access token in the url fragment of the redirect_uri, and this token authenticates you to access protected resources. However, scope parameter also plays an important to determine resources and its entitlements.
Http Request URI
https://YOUR_AUTH0_DOMAIN/authorize?
audience=YOUR_API_AUDIENCE&
scope=YOUR_SCOPE&
response_type=YOUR_RESPONSE_TYPE&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://YOUR_APP/callback&
nonce=YOUR_CRYPTOGRAPHIC_NONCE&
state=YOUR_OPAQUE_VALUE
I will highly suggest to go with Authorization Code Grant with PKCE even for the js applications because the access token is vulnerable to various security risks. With PKCE, the attacker needs to solve the puzzle (code challenge) in order to get the access token.
So after reading lots about BasicAuth, OAuth, JWT... etc. i came up with this question.
I have a client where some ppl can log in (Authentication is done). When ppl want to do an api call they use the clients GUI and the client is sending some requests to the a webservice endpoint.
host/resources/{id}
//id=path, res=post
public Response updateResourceById(String id, Resource res) {
....
So a typical update call could be
POST host/resources/1234 -d={ some json for a resource }
Now i don't want every user to have all rights for every reosurce, so i would
need to add some info about the user who is doing a request.
For this i was thinking to use some JSON Token with some payload (or any user info at all). But i was wondering how to send this token correctly in a RESTful API.
My first idea would be to change the code to something like this:
//id=path, token=post
public Response updateResourceById(String id, Token token) {
...
The endpoint would not change only the POST data.
Would this be correct or are there other approaches?
Edit: Also possible would be sending the Token via HTTP Header.
Sending credentials in HTTP
In HTTP, the credentials should be sent in the standard HTTP Authorization header.
Have a look at the RFC 7235, the current reference for authentication in HTTP 1.1:
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.
In a token based authentication, the tokens are credentials. In this approach, hard credentials such as username and password are exchanged for a token that is sent in each request to identify a user.
It never hurts to say that you should use HTTPS when sending sensitive data, such as credentials, over the wire. HTTPS will protect your application against the man-in-the-middle attack.
Reading the authentication token in JAX-RS
You can read the Authorization header in a JAX-RS application as following and then check if the token is valid:
#GET
public Response myMethod(#HeaderParam("Authorization") String token) {
...
}
However, a better approach would be using a ContainerRequestFilter, keeping your endpoints leans and focused on the business logic. For more information on token based authentication and on how to use a ContainerRequestFilter, have a look at this question.
I want to create an applicacion with angular js and REST services with JWT and out oauth. I want to know how to implement refresh token or the way to generate a token for a week for example, what I have to do?
The architecture is: Java , REST, Angular.js and Bootstrap
user send login and password
the server return token
app user token for access to rest api
rest return result
It’s definitely possible to implement a token authentication scheme without implementing the entire OAuth framework. Your solution would need to have the following characteristics:
It needs to exchange credentials for access tokens and refresh tokens (password grant flow)
The tokens you create should be signed with a key that is private to the server
Authenticate requests that present an access token. It needs to verify access tokens by asserting that the signature is valid and the token is not expired
It needs to issue new access tokens if a valid refresh token is presented (refresh token grant flow)
Access tokens should have a shorter lifetime then refresh tokens
It should reject refresh tokens if the refresh token has been revoked (you need to maintain a blacklist of revoked tokens.
It should do extra checks when the refresh token is being used to get a new access token: is the account still enabled? Or any other check that is relevant to your business logic.
An open-source solution is Kong.
If you’d like to offload this infrastructure, you can consider a product like Stormpath which can add the Oauth2 token framework to an existing application via our Java Integrations. Disclaimer: I work at Stormpath and I think that access tokens and refresh tokens are the best!
I confused with basic http authorization. It is needed to send every request to server with Authorization header or just first one and after that browser rember auth tokens like session id?
You have to send the Authorization header on each request. But for example Chrome remembers the auth tokens and sends it automatically on each request.
Using basic authentication, every request needs to have an Authorization HTTP header in the format:
Authorization: Basic <base64(username:password)>
where the username and password are concatenated using a colon (':') and the resulting string is base64 encoded.
If the Authorization header is not part of the request, or the credentials inside are not valid, the server should respond with an HTTP 401 Unauthorized response and include a HTTP header like:
WWW-Authenticate: Basic realm="myRealm"
Basic authentication is an implicit authentication scheme, so after the user enters valid credential, the browser will send them along with each page request.
For AJAX requests you'll need to attach this header from code. However, you really should not use basic authentication to protect an API, for a number of reasons:
You'd force the client to hold those credentials in code, where they can easily be stolen.
You must use HTTPS with basic authentication as base64 encoding gives no protection of the credentials at all.
Username/password combinations are usually valid much longer than an access token, thereby increasing the risk if they get stolen.
Password validation should be a slow process to mitigate brute force attacks, where token validation is just verifying a digital signature.
Having to send the username/password over the wire every time increases the attack surface for someone trying to break the encryption.
Better alternatives to protect web APIs are token based authentication schemes like OAuth2 or HMAC based authentication schemes like Hawk or AWS
Ya that's correct , so for first time when user logs in , his credentials are verified against some data , if correct , a auth token is generated.
Auth token is pretty much a self contained entity (which stores some data signed with a key)
this token gets stores at client side(usually along with a refresh token)
for all subsequent requests , this token is kept in Authorization header(Bearer+token)
When server receives this token , it decrypts it with the key , which it used earlier to sign that token. And uses that stored data
If that auth token is expired , refresh token comes into play.
some links to begin with
On a high level, how does OAuth 2 work?
and jwt.io to get the feel of tokens