Replacement for deprecated Spring Security JwtHelper - spring-security

I make use of the class org.springframework.security.jwt.JwtHelper from org.springframework.security:spring-security-jwt:1.1.0.RELEASE for decoding JWT tokens, e.g.
Jwt jwt = JwtHelper.decode(accessToken);
String claims = jwt.getClaims();
The above classes are deprecated and the deprecation comment points to Spring Security OAuth 2.0 Migration Guide.
This guide does not talk about any replacement for JwtHelper.
I found the class JwtDecoders which creates a JwtDecoder in the new spring-security-oauth2 project. But JwtDecoders requires an issuer to be passed.
Since I do not wish to verify the token, is there a simple alternative available? Otherwise I can split on . and base64-decode the token, and use any JSON library to parse.

The replacement used in Spring Security is nimbus-jose-jwt. If you don't use Spring Boot, you have to choose a version otherwise Spring Boot will choose one for you.
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
</dependency>
You can just use it like this:
import com.nimbusds.jwt.JWTParser;
....
JWT jwt = JWTParser.parse(accessToken)
Header = jwt.getHeader();
JWTClaimsSet jwtClaimSet = jwt.getJWTClaimsSet();

This worked fine for me without any new dependency
Jws<Claims> claimsJws = Jwts.parserBuilder().setSigningKey(Keys.hmacShaKeyFor("secretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecretsecret".getBytes()))
.build().parseClaimsJws(token);
String username = claimsJws.getBody().getSubject();
Authentication authentication = new UsernamePasswordAuthenticationToken(username,null, null);
SecurityContextHolder.getContext().setAuthentication(authentication);

Do not skip token verification! Failure to verify the token properly will result in an insecure app.
It is very important that you check the issuer (iss claim) of the token and verify it is correct and that it is supposed to be accepted by your application. Only accept tokens from issuers that have the authority to grant access tokens for your app.
Also verify the token is intended for your app (check aud claim): you don't want users misusing tokens intended for other apps (e.g., if user has token with all the right claims, but with aud claim set to another app; that shouldn't be a valid token for you).
Now, make certain to check the signature of the token to verify it is actually signed by the issuer and it is not a bogus token: you can find the issuer's public keys by contacting the issuer. If you don't get the public key directly from the issuer, and you don't verify the signature of the incoming token properly, a malicious user will be able to forge a seemingly-valid token that your app will accept, and your app will be at risk of leaking catastrophic amounts of data.
The last step is to check validity (is it expired?) and to then to check for whatever other claims or scopes your app expects and requires.

If you wish to avoid an additional dependency (e.g. nimbus-jose-jwt), feel free to fork or copy this small utility class: JwtUtils.java

Related

How to verify an apple JWT using a public key

I was following the instructions as mentioned here but I don't understand how to verify the token with the public key. This needs to be done before the what to validate step. I'm not even sure how I'd generate the public key. I understand hitting the apple get request for the JWKS but what do I do after that.
It would be great if someone could simplify this further.
Long story short: use Auth0 lib to check the token signature based on a token you will get from the JWT provider. Here is an example on how to do it based on Keycloak issued token, but with apple the only difference will be with maybe different cypher and public key retrieval method https://youtu.be/Dr4Ae61KGsM

Twinfield do you need sessions if using oAuth?

I’m updating a third party app that currently integrates with Twinfield using the session’s method with username and password to use the oAuth method.
In confused by the documentation though... do I still need to use the sessions or when using oAuth do I just call the endpoint(s) by passing the access token in the header as normal?
Also their Soap definition has four properties, the usual ClientID and Secret but also accessSecret? What’s that?
TLDR: you no longer need to use the sessions and SelectCompany; when you have the access token you can use that and the company code directly in the header.
You can obtain the access token as described here.
The documentation is a bit unclear on how to use the access token in your calls.
In the old username/password/session flow, you referred to a SessionID in the SOAP Header, and you would do a SelectCompany call to select the relevant target ("administratie").
In the OAuth flow, the SessionID is no longer relevant. Once you obtained a valid access token, you should set that in the header using the AccessToken field.
Instead of the old SelectCompany call, you can set the CompanyCode directly in the header. So if you have obtained an access token eyWhatANiceToken, and want to retrieve data for company "My Company BV [130001]" you have set AccessToken to eyWhatANiceToken and CompanyCode to 130001 in the header.
You can request the available codes using the list offices call

Does PHPMailer with oauth2-google use get_oauth_token

We’ve implemented PHPMailer with oauth2-google (via GitHub): no problem.
But I am trying to understand the logic behind the use of the get_oauth_token grant code.
When run standalone, it simply ‘loops’ to the authorization endpoint and back to get an authorization token and then uses this to request an access token and a refresh token from the token endpoint. Developer then pastes the refresh token as a parameter in the instantiation of PHPMailer’s OAuth wrapper class. All very straightforward.
My puzzle is whether:
get_oauth_token.php is then used by PHPMailer OAuth plus theLeague’s OAuth-client
or
whether the latter get authorization and access tokens (and if necessary a new refresh token) themselves without calling get_oauth_token.
The redirectURI (i.e. the URI of get_oauth_token) is not passed to the Google provider instantiation in the PHPMailer published example, and our working (so far...) implementation doesn’t do so either. So I assume it doesn’t use get_oauth_token or any similar callback mechanism since the redirect URI necessary would need to be defined in advance to Google Developer console in the way it is for get_oauth_token itself. But thephpleague / oauth2-google's Readme.md indicates that one should be specified.
However … theLeague’s OAuth-client’s Abstract Provider class includes a __construct to set some options that include redirectUri. Later on in getAuthorizationParameters it sets a redirectUri if one hasn’t been provided, and redirectUri is used in e.g GetAcccessToken.
Can anyone shed light on exactly how redirectURI is being used in this context?
The redirectUri is required in order for Google to redirect back to the originating website to complete the OAuth transaction, after the user logs into Google. Once the access and refresh tokens are available, the redirectUri will (probably) never be used, unless the refresh token is invalidated.
I don't understand what any of this has to do with PHPMailer, so I can't answer that part of the question.

Validating jwt on native platforms

I'm building an native iOS app, it uses OAuth 2.0/OIDC for authentication and authorisation. The auth server is identity serverver 4.
By going thru documents such as https://www.rfc-editor.org/rfc/rfc8252 I have established that the correct flow to use is "authorisation code" flow even though we own the app, the auth server and the resources.
I also learned that we need to use a secure browser such as SFSafariViewController and that we need to use PKCE and remember to use the "state" key in the request and validate on return.
My problem is validating the jwt on the iOS device. I use https://github.com/kylef/JSONWebToken.swift as suggested on jwt.io
To validate the validity of the jwt we need to check that it was is deed signed by our auth server. The server signs using an async rs256 key and exposes the public key on a endpoint. JSONWebToken.swift does not support rs256 and I have not been able to find any iOS library that does, so how to other people validate jwt on iOS devices? I guess we could swith to HS256 which is supported by JSONWebToken.swift but this is a sync algorithm and would require us to store the key on the device which would not be safe.
How to solve this issue, surely I'm not the only one having it...
You could use the Vapor package at https://github.com/vapor/jwt which does support RS256, but you'll need to fetch the JWK yourself.

Client Credential Grant fails on AuthorizeRequest due to lack of Refresh Token

A client credential grant does not return a refresh token (DotNetOpenAuth.OAuth2.AuthorizationServer.PrepareAccessTokenRequest forbids it). But ClientBase.AuthorizeRequest requires it.
Is this a bug in DotNetOpenAuth or am I doing something wrong?
I suppose I can work around by inheriting ClientBase and overriding AuthorizeRequest. Is that the correct thing to do?
Edit: It's not so easy to inherit from ClientBase outside of DotNetOpenAuth because a lot of the stuff you want is internal only. e.g. ErrorUtilities.VerifyProtocol
Edit2: Just read the draft OAuth 2 spec (draft 25) referred to in DotNetOpenAuth.OAuth2.AuthorizationServer.PrepareAccessTokenRequest and I can't find where it disallows refresh tokens for Client credential grant type. Maybe they changed it?
Google returns Refresh Token if you request it. Provide parameter in query string access_type=offline.
In my case I had to amend default Authorization Endpoint URL to: https://accounts.google.com/o/oauth2/auth?access_type=offline
Google Api C# example using DotNetOpenAuth:
private WebServerClient GetClient()
{
return new WebServerClient(
new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline"),
TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
ProtocolVersion = ProtocolVersion.V20,
},
clientIdentifier: this.settings.GoogleApisClientIdentifier,
clientSecret: this.settings.GoogleApisClientSecret
);
}
NOTE from my experience: This works only for the First request.
See Google Documentation.
I'm not sure why you say that ClientBase.AuthorizeRequest requires it. Firstly, there is an overload that only takes an access token, so it doesn't even ask for a refresh token. The overload you may have tried accepts an IAuthorizationState object, which may or may not include a refresh token, and it appears that that method only looks for a refresh token if the access token has expired. Since an expired access token can't be used, it tries to refresh it and throws if it can't. It seems reasonable to me.
Whichever method overload you choose to call, your calling mode must either avoid using expired access tokens or be prepared to respond to the exceptions that are thrown when DotNetOpenAuth or the resource server determines that they are expired or revoked. In fact since tokens can be revoked before they expire, it's a good idea to always be prepared for that.
The OAuth 2 spec draft 25 does in fact indicate that a refresh token should not be included in a response to the client credentials grant. From section 4.4.3:
4.4.3. Access Token Response
If the access token request is valid and authorized, the authorization server issues an access token as described in Section 5.1. A refresh token SHOULD NOT be included. If the request failed client authentication or is invalid, the authorization server returns an error response as described in Section 5.2.

Resources