Does the client call back the server with the same JWT token it received? - security

I am new to JWT and hence trying to understand the intricacies and expectations when using JWT. In my case, I own the micro-service generating the JWT tokens. JWT supports RS256 and HS256 mechanisms. From what I understand, in case of RS256, I distribute the public key to my client. In case of HS256, I distribute the secret to my client.
Assuming I give access to either of these to my client, what is the expectation from the client? Should the client treat the token I passed back to them as immutable and they just send me the exact token back in the subsequent API calls? Or is it recommended/ okay for them to mutate the token and create a new one, for e.g. by changing things like audience in the token payload, and then for my server to verify the newly passed token? My server should be able to verify both tokens, but I don't know which is the recommended approach. If the recommended approach is for my client to not mutate the token, why do I need to distribute the keys to the client in the first place?

Do not distribute the key to the client. The client should not be able to modify the JWT access token. It should treat the token as opaque.
Only the resource server (exposing the API) that accepts the token should verify the signature.
In OAuth2, the client is the application getting the access token and using it to call an API server. It should not care about the token as long as it works to call the API.
The authorization server authenticates the user, gets the user's consent and issues the token to the client.
The client then uses the token to call the resource server (API) with the token in the Authorization header.
In your case, the authorization server and resource server may be the same, but they should not share signing keys with the client.

Related

For user verification, you do need to store data on server side even when using JWT correct?

While I understand how jwt works for authentication, I'm trying to build registration.
Registration has a step that requires verification.
User enters the phone number
Code is sent via sms to user
User enters the code and device is verified
Since it's an API for mobile app there is no session/cookie built in.
I'm wondering if I can not implement cookie like system for mobile. And just make it work with JWT. But I don't have much experience with this.
This is my current flow:
User makes a POST request with Phone #
I respond with JWT (Time:Number)
I also send code via SMS
User sends the code via POST and JWT
Problem:
I don't know if code belongs to user or not, as I didn't save the code in DB.
I can't put into payload as it's just encoded not encrypted. (why is it not encrypted, what's the point of sending plain payload, what's even the point of JWT & didn't signed cookies already do that? they had session string encrypted so you couldn't change session string without invalidating the cookie)
JWT is overcome authentication/authorization mostly in APIs. JWT Access Token/Refresh Token is nothing but a JSON data in an encrypted form. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. Key pair using RSA or ECDSA is more preferable as a security point of view. You can check authentication/authorization by decryption JWTs.
JWT token itself contains expiry date, so you can just configure expiration time to it. Access tokens are to check that user is authorized or not. Refresh tokens is necessary to get a new access token, generally used when the old access tokens are expired. Refresh token and Access token both expire but refresh token is long-lived compare to access tokens.
Generally developers use access token only but it is preferable to use access and refresh token both.

OpenID Connect - should the id token be sent to the protected resource in this case?

Lets say I have a web API that a native application needs to make requests to. This API needs to authenticate who the user is that's making these requests via the native app. OpenID Connect seems to be the right choice since it is about authentication rather than authorization with OAuth.
The native app sends the users credentials to the IDP and gets back an access token (for authorization) and an id token (for authentication). From what I understand of OIDC, the access token would be sent to the API but the id token is only for the native client app. That doesn't make sense to me because it's the API that cares about who the user is, not the native app.
So why isn't the id token also passed to the protected resource (aka the API)? If you don't pass the id token to the API, what guarantees that the access token is secure and can be used to authenticate the user? Otherwise it would seem to lose the benefit of using OIDC over OAuth.
The OIDC Specification is designed in a way that ID tokens are always for Clients (Native app) and Access tokens are for resources (APIs). The ID tokens are always JWT tokens, but the Access tokens can be of different type.
The purpose of Access token is not to authenticate but to Authorize (Delegated Authorization). If, for some reason, the resource server wanted to know about the user, it can call the user-info endpoint.
The security/validity of token exchange can be validated in several ways:
Using encryption/signature with Public/Private key model where Authorization server encrypts / signs the access token with its private key and resource server decrypts / verifies with the public key.
Using token introspection endpoint to validate the claims, validity of the token etc..
Other attributes like AUD , AZP help in validating the issued access tokens.
Some OIDC providers use ID_Tokens to access API's - this is different to the model suggested by OIDC specification
This article has detailed explanation about these scenarios.

Correct Micro Service JWT flow

I am currently building out a micro service architecture and started with the auth server and client. I also wanted to confirm the best flow of authenticating a user with a token.
In the above image. Step 3 is were I start getting confused.
I thought of 2 solutions to the problem.
One every api passes the token to the auth server and waits to get approval that the token stored inside matches the db and it is still valid.
Two is to include a secret phrase in the JWT token and just have the API service parse and check for itself if the token is valid.(The secret phrase would be so that if a hacker tried to fake a token and it parsed to a valid id somehow the phrase would be off without the secret code used to encrypt the token. Which I don't even know if it is possible. If not then I guess 2 would be the best course of action)
A hacker cannot create a valid JWT token if he does not know the the signing key. If he somehow manages to get that signing key it is reasonable to assume that he is able to get your "secret phrase" also.
About the checking: JWT tokens can be checked by the API service as they contain all the information needed (except the signing key that must be known by the API service). The expiration can be checked here also. Anyway, you also need the information stored inside the token, like user ID. You should do this if you want better scalability.
The only reason why you would need to check a JWT token against a third Auth service is to see if it has been invalidated; for this you need a central service although you could replicate the list of invalid tokens to all the API services for better resilience.
You really don't have to forward the request to Auth-server to validate the JWT token. A JWT token is like a bill note, once it's signed it can be validated by anyone who is sharing the key.
I would recommend you to have an edge service in front of all your API-services. The edge service either shares the key by which JWT token is signed by Auth service or has the public key to verify the signature.
Once the signature is verified, the edge service can extract the required information from the token and add it to request header. Your downstream services can consume this information according to their need.
You can use Https to enforce that your request isn't intercepted by anyone over the network. In case, even if someone tries to mess up with the JWT token, the signature won't match and you can detect that. Please go through JWT/KONG: Cannot create JWTs with a shared secret to know more about creating-parsing the JWT token with public-private keys.

Using SAML with JWT for Node API

I'm building an Angular 2 application using SAML2 via the passport-wsfed-saml2 strategy https://github.com/auth0/passport-wsfed-saml2. When I receive a users info back from SAML I generate a JWT token which I use to authenticate a user on an API I am also writing.
So I have two servers, APP/Auth Server is serving my application as well as generating my JWT tokens and API Server has my API. Both servers have a copy of the JWT secret, so when a user sends a request from APP/Auth Server to the API Server I verify the token they sent with their request by verifying it with the secret.
Now for my questions, is it bad practice to have your app served from the same server you use to generate your JWT tokens? If so, what should I do here? Should I be doing more to authenticate a user on my API side?
Something about this just feels dirty....any help would be appreciated.
Having the application and authentication system in the same service is not a malpractice by itself. In general, decoupled services are recommended but this does not mean that the deployment can group services and of course depends on the context
If you are worried about sharing the secret key among servers, you can use an asymmetric key pair (private and public). The private key only needs to be known by the Auth Server in order to sign the JWT. The API Server can use the public key to verify tokens.

Restricting traffic to server from only my mobile application

I have a requirement to secure my JAX-RS resources and only accept requests that originate from authorized mobile applications. Is this possible? How can this be done?
All of my resources are protected already with user authentication, the goal here is to reduce user ID fishing attempts. I know one solution would be to keep the response error with an invalid user ID generic, but the application is very large and at the moment this isn't possible.
One idea I came up with is to use JWT tokens signed with a shared secret. Then I could add an Authorization filter on the server to check the signature. If it doesn't validate then discard the request. Does this sound like a viable option?
My concern is the security of the shared secret on a mobile device, could it be compromised with a rooted device?
Using tokens is the preferred way. But the secret key is not shared. Only the server has access to it. That secret key is used to generate the message authentication code(MAC) of the JWT. Since secret key is only known by the server, no one else can generate a JWT with a valid signature. Secret may be persisted or application scoped.
Once a client is authenticated using credentials, server must send a signed JWT to the client.
That JWT must contains necessary information to identify the client and state(if necessary).
Then client send that token in a header field along with all the other requests.
Server validates the JWT using secret key and process the request.
Even though client can change the JWT body, he cannot get it verified. That's the whole point of using a signature.

Resources