OAuth2 Social Provider - JWT parameters - jwt

Found this nifty proposed document on what params to put into a JWT for the state parameter when doing an OAuth2 authentication with a social provider like facebook, twitter, discord, etc.
Link: https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-00
The state JSON Web Token claims
The OAuth Authorization request "state" paramater consists of a
[JWT], optionally signed with [JWS] or encrypted with [JWE], whose
payload contains claims as defined here.
rfp
REQUIRED. string containing a verifiable identifier for the
browser session, that cannot be guessed by a third party. The
verification of this element by the client protects it from
accepting authorization responses generated in response to forged
requests generated by third parities.
kid
RECOMMENDED if signed. Identifier of the key used to sign this
client identifier at the issuer.
In the above section, should rfp (Request Forgery Protection) value be a nonce or the user's authentication cookie I previously cookied them with? I'm thinking it should be a nonce because the auth cookie is kinda long and may expire between the time they authenticate and hit my callback route.
If I use a secret string to sign my JWT and in my .env I call it JWT_SECRET, should the kid parameter above be JWT_SECRET?

Related

How to get the Username with OpenID Connect on ADFS Server

I just realized that the userinfoendpoint doesn't give any useful info about the logged in user.
Now, I saw that you can get an id_token from ADFS tokenendpoint. This id_token is actually a JWT which contains the unique_name.
Now my question is, if it is safe to use this info without signature validation (since we don't have the private key of the HS256 algorithm and validation is as far as I understood, a thing for the issuer not for the client).
• There are two scenarios to your question of whether it is safe to use this info from an ID_token. First, your client, i.e., the application or authorization server will validate the token just like it validates the access token for any tampering. Also, it can validate the issuer to ensure that the correct issuer has sent back the token. Since there are many libraries to validate an ID token, you should use them for ID token validation purposes.
• Also, only confidential client applications should validate an ID token as their token holds a secret while public applications don’t benefit from validating an ID token as there is always a risk of a malicious user who can intercept and edit the keys used for validation of the token.
• As you are speaking of the case when you don’t have the private key to the algorithm used for encrypting the ID token, it must be a confidential client application. Thus, validating the ID token on the lines of access token and confirming the below claims are validated by your token validation library, you can then use the information retrieved from these claims for your purpose. The claims that need to be validated are as follows: -
Timestamps: the iat, nbf, and exp timestamps should all fall before or after the current time, as appropriate.
Audience: the aud claim should match the app ID for your application.
Nonce: the nonce claim in the payload must match the nonce parameter passed into the /authorize endpoint during the initial request.
Please find the below documentation link for more in-depth details on validating the tokens and the inherent process involved in it: -
https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens#validating-tokens
No, sadly the userinfo endpoint only gives you a "sub".
You can validate the JWT yourself.
You should always check the signature.

Authorizing access to resource in a REST API

I am new to building API's and I am having trouble understanding how to perform the following task reasonably.
There is an endpoint:
/user/{user_id}
which retrieves the details of the user.
The frontend code will request this endpoint to get details about the user to display on the dashboard.
I have to protect this endpoint so that a user who doesn't represent this user_id, emulates the request to get information about other users.
Since REST based API's are sessionless, I cannot store session keys. So how do I make sure that the server sends the user information only if the owner of the user id has requested it?
You are right. HTTP is a stateless protocol, therefore REST inherits that quality too.
Here is the deal in simple words.
[REST client] -------> [API endpoint]
You have many REST clients, and you need to make sure that only authorized users will grant the access to your API endpoint. One solution as #James suggested is use a token mechanism such as JWT https://www.rfc-editor.org/rfc/rfc7519.
If you consider JWT authentication, the process flow will be as follows.
[REST client] -------> [AA service]-------> [API endpoint]
You will need an AA(Authorization, Authentication) service in the middle. For example in a microservices approach, this can be performed from a API gateway which is a gateway to all of your services.
Client will give AA service their username and password. In exchange AA service will give the client a JSON token signed only by the server so that the confidentiality is protected. This token contains 3 things.
Header which specifies the type of token and algorithms used to sign it
Payload which includes claims like to whom the token is issued, when should the token expire, what is issued user's role should be etc. (see https://www.rfc-editor.org/rfc/rfc7519#section-4)
Signature which a product of unsigned token signed by the server key
Then you encode each header, payload, signature with base64 and concatanate with a ".". You now have a JWT.
AA service returns this JWT in exchange for credentials.
Client should store this token securely (ex: local storage) and the communication medium should be encrypted(ex: TLS). See https://stormpath.com/blog/jwt-the-right-way#how-to-secure-jwt , https://www.rfc-editor.org/rfc/rfc7519#section-6
After that for every subsequent REST call, client should include the received token, preferably in the Authorization header although it is technically possible to send the token in the message payload as well.
Then it is AA service's responsibility to decrypt the token using its signing key evaluate claims in the JWT and act upon whether to authorize the API call send him HTTP 401,403 responses.

JWT and CSRF differences

I've been reading about JWT, and from what I understand, it's a token that the server sends after a user logs in. The user will have to send that token with all future HTTP requests. This creates a stateless way for the server to verify a user's request.
Now what I don't understand is that if the JWT is sent in the header and marked as HTTP only, why is a CSRF token also needed for prevention of CSRF attacks? My understanding is that both JWT and CSRF tokens are tied to a user, and that a JWT would serve both purposes.
I understand that CSRF tokens are used so HTTP requests from other sites won't be accepted. How does a JWT not accomplish that? What separates a CSRF token from a JWT token, and allows it to accomplish that difference?
I've been reading articles on JWT's and CSRF tokens as well as the double submit method, but there is just something I can't seem to understand or I'm missing.
An authentication system based on tokens (JWT or random) stored in cookies is vulnerable to CSRF attacks, because cookies are sent automatically to server in each request and an attacker could build a harmful url link to your site.
https://yoursite.com/delete?something=1
To protect your site it is needed to use a CSRF token that your application must send in the following request (not in a cookie).
Alternatively you could store the JWT in localStorage and send it in a Authorization header, then your site is protected against CSRF, but it could be vulnerable to XSS attacks. Take in account always the security considerations of the technical solution you choose
Update ¿why storing JWT in localstorage could be vulnerable to XSS attacks?
See this comparison between storing tokens in localstorage and http-only cookies https://academind.com/tutorials/localstorage-vs-cookies-xss
An attacker could inject javascript code to read the token from the localstorage and send it to his own server. However, this type of attack is not possible with an http-only cookie because it is not accessible from javascript
All your questions are relative to the fact that a CSRF token in NEVER included in a cookie and that a JWT token MAY be sent in a cookie.
A JWT token can be sent:
1- in a cookie
2- in another type of header
3- outside the headers, in some POST attribute
4- outside the headers, in some GET parameter (not very common)
But for stateless authentication, you MUST use cookie (case 1).
So, for stateless authentication, you are prone to CSRF, with your JWT token. This is why you need to add some CSRF mitigation mechanism, based on some more information not included in a cookie, or not only included in a cookie.
All of this would not apply if you were accepting to implement a stateful authentication.

Process JWT token using JWKs Endpoint

I receive two JWTs: an OpenID Connect ID token (id_token) and an Access Token (access_token). The situation with OpenID is more or less clear - I can validate it using a JWKS Endpoint: https://smth.com/JWKS.
as in example (https://bitbucket.org/b_c/jose4j/wiki/JWT%20Examples):
HttpsJwks httpsJkws = new HttpsJwks("https://smth.com/JWKS");
HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
jwtConsumer = new JwtConsumerBuilder()
.setVerificationKeyResolver(httpsJwksKeyResolver)
.setExpectedAudience(...)
.setExpectedIssuer(...)
.build();
The question is how to proceed with the Access Token. I can extract from it the userId and userDetails, but I guess I need also to validate it?
If I try to validate the Access Token the same as for the ID Token, I am getting this error:
UnresolvableKeyException: Unable to find a suitable verification key for JWS w/ header {"alg" : "RS256", "kid":"1"}
And indeed there is no key for "kid" : "1", Also this value "1" seems kind of strange?
Am I doing something totally wrong?
It sounds like you are implementing the role of OpenID Connect client or Relying Party. The two tokens, ID token and access token, serve different purposes and should be handled differently by the client. The ID token is intended for the client and enables authentication of the end-user at the client. The client must validate the ID token (verify the signature and validate claims like exp and aud, etc.) before allowing the end-user in. The access token, however, is for the client to use to access resources or APIs but is not directly intended for the client to consume or validate. The access token is opaque to the client and the client shouldn't care or know about its details. In fact, access tokens aren't always JWTs. In OpenID Connect, the access token is used to call the user info endpoint (with the HTTP header, Authorization: Bearer [access token]) to get more claims/info about the end-user.
The value of "1" for the kid is totally legal but it is referring to a key that the AS/OP and the user info endpoint know about somehow. It is not a key at the OpenID Connect JWKS endpoint. "1" isn't a key that the client needs to know about because the client isn't supposed to directly verify the access token.

RESTful authentication scheme

I need to implement an authentication scheme for a RESTful architecture. From several articles which I have read include basic Authentication using HTTPs and Session management using Cookie.
However I'm not well understanding the use of cookie. What i understands is that user first sends credentials. The server checks if the credentials are Ok. If yes, the server generates an authorization token and place it in the cookie. Onwards, on each and every request, server checks the validity of the token in the cookie.
But how does the server know that the content of the cookie is valid. Does it stores it somewhere and then it compares it??
The key point here is the authorization token. When generating one and sending back to the client, you store the auth token along with the username in let's say a database. You store the auth token in the cookie. The client on subsequent requests sends you the username and the cookie alongwith which contains the auth token. You verify this token against the supplied username and then perform the action per need.
However, do note that settings cookies makes your webservice call stateful and defeats the purpose of REST.
To achieve authentication/authorization, instead of setting the authorization token in the cookie, send it back as a response value. The client reads the value of auth token and then supplies the same in every REST request as a parameter of request body. Thus, you won't need to set cookies. This you may term as the toned down and simpler version of what is implemented in OAuth based API access.
I'm not an expert, but a good starting point to understand this is the section on Sessions in Hartl's book.
If I'm not mistaken it works as follows:
When the token is created, it uses a formula, e.g. the username and a unique user key (a salt) encrypted together. Both the username and the salt are stored in the database, and the salt is unique to that user. So, as you would do to compare if passwords match, to check the validity of the cookie you recreate the token and compare it to the one in the cookie. If it matches, then the right user is logged in and therefore authorised.
Hope this helps, or at least points you in the right direction :)