Skip to content

Latest commit

 

History

History
313 lines (257 loc) · 7.18 KB

demo.adoc

File metadata and controls

313 lines (257 loc) · 7.18 KB

Java OAuth Demos

This demo shows how to build a Spring Boot app and secure it with OAuth 2.0. Then, it shows how to create resource servers with Quarkus and Micronaut.

Prerequisites:

Create a Spring Boot app using Spring Initializr

Use start.spring.io to create a new Spring Boot project with OAuth dependencies.

https start.spring.io/starter.tgz \
  dependencies==web,oauth2-client,oauth2-resource-server \
  baseDir==spring-boot \
| tar -xzvf - && cd spring-boot

Configure Spring Security

  1. Ensure it starts and you can log in as user.

    ./gradlew bootRun
  2. Add your Auth0 domain to application.properties to configure a resource server.

    spring.security.oauth2.resourceserver.jwt.issuer-uri=https://<your-auth0-domain>/
  3. Add a HelloController.java file with the following code.

    @RestController
    class HelloController {
    
        @GetMapping("/hello")
        public String hello(Principal principal) {
            return "Hello, " + principal.getName() + "!";
        }
    }

Test your Spring Boot Resource Server

  1. Run the app using Gradle.

    ./gradlew bootRun
  2. Open a new terminal and use HTTPie to test the resource server.

    http :8080/hello

    You will get a 401 response.

  3. Create an access token using Auth0’s CLI:

    auth0 test token -a https://<your-auth0-domain>/api/v2/
  4. Set the access token as an environment variable:

    TOKEN=eyJhbGciOiJSUzI1NiIsInR5cCI6...
  5. Access your resource server using HTTPie:

    http :8080/hello "Authorization: Bearer $TOKEN"
  6. You should receive a 200 response with a message.

    Hello, auth0|61bcbc76f64d4a0072af8a1d!
  7. Stop the resource server using Ctrl+C.

Add OpenID Connect Authentication to Spring Boot

  1. Create a SecurityConfiguration.java file that contains the same defaults as Spring Security.

    @Configuration
    public class SecurityConfiguration {
    
        @Bean
        public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
            http.authorizeHttpRequests(authz -> authz.anyRequest().authenticated());
            http.oauth2ResourceServer().jwt();
            return http.build();
        }
    }
  2. Confirm you can still access the /hello endpoint.

    http :8080/hello "Authorization: Bearer $TOKEN"
  3. Modify the SecurityFilterChain bean to enable OIDC authentication.

      @Bean
      public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
          ...
          http.oauth2Login();
          ...
      }
  4. Create an OIDC application using the Auth0 CLI.

    auth0 apps create --reveal-secrets
    • Name: Spring Boot

    • Type: Regular Web Application

    • Allowed Callback URLs: http://localhost:8080/login/oauth2/code/auth0

    • Allowed Logout URLs: http://localhost:8080

  5. Update application.properties to include these values, removing any previous properties.

    spring.security.oauth2.client.provider.auth0.issuer-uri=https://<your-auth0-domain>/
    spring.security.oauth2.client.registration.auth0.client-id=<client-id>
    spring.security.oauth2.client.registration.auth0.client-secret=<client-secret>
    spring.security.oauth2.client.registration.auth0.scope=openid,profile,email
    auth0.audience=https://<your-auth0-domain>/api/v2/
  6. If you start your app, it’ll fail with the following error:

    Method filterChain in com.example.demo.SecurityConfiguration required a bean of type
      'org.springframework.security.oauth2.jwt.JwtDecoder' that could not be found.
  7. Add a JWT decoder bean that does audience validation.

    @Value("${auth0.audience}")
    private String audience;
    
    @Value("${spring.security.oauth2.client.provider.auth0.issuer-uri}")
    private String issuer;
    
    @Bean
    JwtDecoder jwtDecoder() {
        NimbusJwtDecoder jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuer);
    
        OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
        OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
        OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
    
        jwtDecoder.setJwtValidator(withAudience);
    
        return jwtDecoder;
    }
  8. Create an AudienceValidator class to validate JWTs.

    class AudienceValidator implements OAuth2TokenValidator<Jwt> {
        private final String audience;
    
        AudienceValidator(String audience) {
            this.audience = audience;
        }
    
        public OAuth2TokenValidatorResult validate(Jwt jwt) {
            OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
    
            if (jwt.getAudience().contains(audience)) {
                return OAuth2TokenValidatorResult.success();
            }
            return OAuth2TokenValidatorResult.failure(error);
        }
    }
  9. Add a HomeController to display the user’s name after they log in.

    @RestController
    class HomeController {
    
        @GetMapping("/")
        public String home(@AuthenticationPrincipal OidcUser user) {
            return "Hello, " + user.getFullName() + "!";
        }
    }
  10. Restart the server. Use Ctrl+C to stop it if it’s running.

    ./gradlew bootRun
  11. Log in at http://localhost:8080.

  12. Use HTTPie again to confirm your resource server still works.

    http :8080/hello "Authorization: Bearer $TOKEN"
  13. You can inspect your access token at jwt.io.

Create a Resource Server with Quarkus

  1. Clone the Okta Quarkus Sample:

    git clone https://github.com/okta-samples/okta-quarkus-sample.git quarkus
  2. Update application.properties to update the public key location. Remove all other properties.

    quarkus.oidc.auth-server-url=https://<your-auth0-domain>
    mp.jwt.verify.publickey.location=${quarkus.oidc.auth-server-url}/.well-known/jwks.json
    mp.jwt.verify.issuer=${quarkus.oidc.auth-server-url}
  3. Run the app:

    mvn quarkus:dev
  4. Verify you can access it with an access token.

    http :8080/hello "Authorization: Bearer $TOKEN"

Create a Resource Server with Micronaut

  1. Clone the Okta Micronaut Sample:

    git clone https://github.com/okta-samples/okta-micronaut-sample.git micronaut
  2. Update application.yml to change the public key location. Remove all other properties.

    micronaut.security.token.jwt.enabled: true
    micronaut.security.token.jwt.signatures.jwks.auth0.url: https://<your-auth0-domain>/.well-known/jwks.json
  3. Run the app:

    mvn mn:run
  4. Verify you can access it with an access token.

    http :8080/hello "Authorization: Bearer $TOKEN"