I want to use OAuth JWT token for authorization. By some reasons (osgi container) I can't use spring-oauth-security.
In the readme of spring-oauth-security I have found a quote:
The JSON Web Token (JWT) version of the store encodes all the data about the grant into the token itself (so no back end store at all which is a significant advantage).
https://github.com/spring-projects/spring-security-oauth/blob/master/docs/oauth2.md
I am absolutely don't catch "no back end store at all". There are two cases in jwt:
symmetric key or shared secret (HMAC);
Verifier key is a shared secret and is available by /token_key URL.
Question 1: I should store shared secret on server for each registered user. Why "no back end store at all"?
asymmetric key (RS/ES);
/token_key returns public key (without principal).
Question 2: But why we use only one public key for all users? It is unable to generate more than one private key for the same public key in rsa, isn't it? Only one pair private key - public key is allowed in RSA.
I don't understand a flow and why "no back end store at all".
You do not use different keys per user but per Identity Provider.
Identity Provider signs a JWT with a key and you are able to validate it for each user without a backend lookup. For JWT validation you only need a key related to the Identity Provider - even if you store it on some DB, you could fetch it once and cache it. For assymetric keys, OIDC even defines a URL to fetch the public key(s) used for signature.
The key is used to trust the Identity Provider and thus implicitly the identities it provides.
This is quite good article on the topic:
https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/
Related
I'm trying to encrypt my sensitive data for an application. For the key generation part, I'm using crypto/pbkdf2. I'm generating the encryption key on the fly based on the user supplied password. When a user is created, that's when I'm encrypting the corresponding data of the user with the user's supplied password. However, whenever that particular user tries to access a resource, I've to decrypt the data before showing it to the user. Where do I get the password from, everytime an endpoint is called by that user to access a resource?
Note: I'm storing the hashed password of the user in the database schema, also I don't want to store the encryption password anywhere!
The typical solution to this is called token-based authentication (or in OAuth terms, Resource Owner Password Credential Flow).
Create a "login" endpoint that will derive the encryption key from the supplied username/password and exchange it for a (time-limited) "access token", storing it in a key-value store with TTL support (e.g. etcd, Redis).
Then each subsequent request will need to supply the access token (e.g. in the Authorization header), which is then used to retrieve the encryption key from the key-value store.
I am looking for documentation on Google oAuth2 JWT token verification process. In my use-case, I am going to send the JWT token from my client and the server code is responsible for validating the JWT token. My backend will be responsible for validating the oAuth2 JWT token as per spec, so I need a formal process on what needs to be done in-order to validate the JWT token instead of just using the libraries.
I am using Spring library to do that, but I am looking for information like how to get the certificates and use them if we are making call to Google API for validation.
If I am client, then all I need is just a client_id and ApiKey. But here I also see that we do need to provide certificates. Please let me know If I am wrong.
For validating a signed JWT, you should look at its header part and the properties alg (algorithm used for making a signature) and kid (signature encryption key ID). Load the Google OAuth 2 discovery JSON document
https://accounts.google.com/.well-known/openid-configuration and read its jwks_uri property (URL with encryption keys). Read the keys from that URL (it's a JSON document) and find a key with use="sig" (used for signing) and matching alg and kid values. Then you can decrypt the JWT signature to get the JWT hash value and compare it with your calculated hash value.
So you don't need to import a key to your keystore. You can cache the keys, but when you get a kid value not contained in the cache, you need to read the JWKS document again. There is also a possibility of Google removing some keys over time.
According to this and this there are two ways to validate the JWT token:
Using RemoteTokenServices which basically calls /check_token endpoint of oauth server, retrieves the whole token and compares it
Expose public key at oauth server and verify the JWT's signature at resource server
At the beginning I tried the first way but since I use custom token converter which hits the database every time token being generated, I decided to switch to signature verification at resource side - didn't want to get an additional database call per every client request.
After some investigation I realized that ResourceServerTokenServices (interface describes token retrieval, conversion and generation a valid OAuth2Authentication object) has only two default implementations: DefaultTokenServices which is primary used in case of oauth and resource servers are parts of the same application and RemoteTokenServices which was described in first approach.
So the main question is whether spring-oauth2 really hasn't default implementation of JWT signature verification or I just couldn't find one?
You do not need a JWT specific ResourceServerTokenServices, so the DefaultTokenServices should do fine. Most of the implementation specific details are sent to the store, so as long as you have a JwtTokenStore configured correctly there should be no issue.
Here :
The Resource Server also needs to be able to decode the tokens so the JwtTokenStore has a dependency on a JwtAccessTokenConverter, and the same implementation is needed by both the Authorization Server and the Resource Server. The tokens are signed by default, and the Resource Server also has to be able to verify the signature, so it either needs the same symmetric (signing) key as the Authorization Server (shared secret, or symmetric key), or it needs the public key (verifier key) that matches the private key (signing key) in the Authorization Server (public-private or asymmetric key). The public key (if available) is exposed by the Authorization Server on the /oauth/token_key endpoint
You can extend JwtAccessTokenConverter to access once the Authorization Server for the exposed public key.
If someone knows the secret key and alters lets say for example the username of the json token and the expiry time, will they be able to access secured data on the sever?
If in "secret key" you refer to the symmetric key used in the HMAC signature then anyone who is in possession of that key can create and sign a valid JWT.
If in "secret key" you refer to the private key used to sign a JWT in the RSA scenario, anyone in possession of that key could create and sign a valid JWT trusted by anyone who is validating using the corresponding public key.
Assuming someone can forge a JWT at will (Is able to sign it correctly after modifying it), this token would be trusted by parties who receive it and its contents would be considered authentic.
So basically, yes.
Here is great read describing some vulnerabilities and on the way the general concepts of security in JWT.
You need 5 different parameters to get the access token -
grant_type, username, password, client_id, client_secret
so, knowing the secret key, username would not get you the Token; Knowing password also would get. It precisely means someone would get the Token only if he/she knows all the parameters, else not!
I am implementing an app that connects to an OAuth2 server and it gets back a Json Web Token (JWT). I am passing the token along and I want to independently validate that the token came from the issuing source.
I can do this, no problem, with the public key from the issuing source. I have it available to me for now. Everything works.
But what if the OAuth server changes the signing key? How does the validating app get the new key? Is there a "best practices" convention for sharing the public key from an OAuth2 server? Do we just expose it from an endpoint on the auth server?
There's no solution that is standardized as part of the OAuth 2.0 protocol suite (today).
It was considered to be a single-domain problem that would be solved in various ways that were considered to be out of scope for the core OAuth specifications (much like the API between Resource Server and Authorization Server is/was), and much like any PKI based mechanism in general works today.
But OpenID Connect is a cross-domain SSO protocol that was built on top of OAuth 2.0, which also defined a more standardized option of dealing with key distribution in the form of JWKs URIs as part of the Discover, see the jwks_uri entry at:
REQUIRED. URL of the OP's JSON Web Key Set [JWK] document. This
contains the signing key(s) the RP uses to validate signatures from
the OP. The JWK Set MAY also contain the Server's encryption key(s),
which are used by RPs to encrypt requests to the Server. When both
signing and encryption keys are made available, a use (Key Use)
parameter value is REQUIRED for all keys in the referenced JWK Set to
indicate each key's intended usage. Although some algorithms allow the
same key to be used for both signatures and encryption, doing so is
NOT RECOMMENDED, as it is less secure. The JWK x5c parameter MAY be
used to provide X.509 representations of keys provided. When used, the
bare key values MUST still be present and MUST match those in the
certificate.
This would expose the key material over HTTPs protected channel, effectively leveraging the SSL CA for publishing and rollover of JWT signing key material.
At some point the jwks_uri definition may be part of the standardized OAuth 2.0 protocol extensions as well, but for now you'd have to rely on a custom agreement between Client and Authorization Server to do so. That may not be too hard to implement yourself though.
You may get lucky if your Authorization Server happens to be an OpenID Connect provider as well and uses the same key material for signing ID tokens as well as JWT access tokens.
Updated 4/22/2019: the Authorization Server metadata document is now also standardized it its own OAuth 2.0 extension OAuth 2.0 Authorization Server Metadata RFC8414