Reputation: 459
My application is mainly based on spring boot micro services. Currently it uses OAuth with password grant_type which is deprecated in the latest spring security authorization server release. For receiving JWT token, it stores client id and client secret in React JS frontend which is not secure and not recommended. Users need to register to access certain resources and application maintains login credentials in mysql DB
I am trying to upgrade spring security and want 'account service' to act as authorization server to issue JWT tokens.
Upvotes: 0
Views: 3147
Reputation: 12659
With OAuth2, clients (your React app) must authorize requests to protected resources, that is provide an access-token as Bearer Authorization
header.
When acting on behalf of a user, clients should use authorization-code flow (with PKCE) to fetch such an access-token from authorization-server.
Also, use an OAuth2 client library in your React app. It will help you to:
Some libs even handle:
I have not enough experience with React to recommend a specific lib, but you can search with "OpenID", "OIDC" or even "OAuth2" keywords
REST APIs secured with OAuth2 are "resource-servers". You can use spring-boot-starter-oauth2-resource-server
directly as done in the first of those tutorials, but it is quite some Java conf.
Instead, you can use one of the spring-boot starters from the same repo. They are thin wrappers around spring-boot-starter-oauth2-resource-server
with sensible defaults and most security conf from properties:
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<!-- replace "webmvc" with "webflux" if your app is a servlet -->
<!-- replace "jwt" with "introspecting" to use token introspection instead of JWT decoding -->
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<!-- this version is to be used with spring-boot 3.0.0-RC2, use 5.x for spring-boot 2.6.x or before -->
<version>6.0.5</version>
</dependency>
@EnableMethodSecurity
public static class WebSecurityConfig { }
com.c4-soft.springaddons.security.issuers[0].location=https://localhost:8443/realms/master
com.c4-soft.springaddons.security.issuers[0].authorities.claims=realm_access.roles,ressource_access.some-client.roles
com.c4-soft.springaddons.security.cors[0].path=/some-api
Basically, nothing to do in regard to authentication and OAuth2: inbound requests to secured resources should have an authorization header already and resource-servers will respond with 401 if authentication is missing or invalid (expired, wrong issuer, ...) or 403 if access is denied (valid identity but not allowed to access that resource)
Any OAuth2 authorization-server would do, but you might choose an OIDC implementation.
Authorization-server will handle users registration, login and logout. It will issue access, refresh and ID tokens, using mainly:
offline_access
scope is requested when authenticating (with any flow), a refresh-token is returned in addition to access-token and can be used to silently get a new access-token when current expires (or just before it does)You can use Spring authorization-server framework to build your own authorization-server, but could also prefer to pick one "off the shelf": there are plenty out there with a lot of features implemented
And this either on premise (Keycloak is a quite popular sample) or SaaS (like Auth0 and many others: almost any cloud provider has its own solution).
Upvotes: 2
Reputation: 129
The newest version of Spring Security mode introduces a new project for the Authorization server in the scope of Spring Security:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.3.1</version>
</dependency>
The authorization server from spring implements OAuth2.1 where as you mentioned, both PASSWORD and IMPLICIT grant types were removed comparing it to OAuth 2.0. Gran types supported in OAuth 2.1: 1
OAuth 2.1 provide authorization code + PKCE grant type but it's a little bit different from the previous.
"The key difference between the PKCE flow and the standard Authorization Code flow is users aren’t required to provide a client_secret. (...) In place of the client_secret, the client app creates a unique string value, code_verifier, which it hashes and encodes as a code_challenge. When the client app initiates the first part of the Authorization Code flow, it sends a hashed code_challenge."
That type of grant type is recommended for SPA application so if you want to use the newest version of spring security you need to use it, because e.g. client credentials are reserved for machine-to-machine communication when one service needs to communicate with another service without of user's knowledge.
Storing only username/email should suffice because users just need to pass client ID and code_challenge to get an authorization code? ClientID and generated code_challenge (should be generated by the client) is something that identifies the client not the resource owner, so user while authorized shouldn't provide this type of info.
Upvotes: 1