### HTTP GET Request with Authorization Header Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt/reader/bearerToken.adoc An example of an HTTP GET request demonstrating the use of the 'Authorization' header with a Bearer token. ```bash GET /protectedResource HTTP/1.1 Host: micronaut.example Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MjI5OTU5MjIsInN1YiI6ImppbWkiLCJyb2xlcyI6WyJST0xFX0FETUlOIiwiUk9MRV9VU0VSIl0sImlhdCI6MTQyMjk5MjMyMn0.rA7A2Gwt14LaYMpxNRtrCdO24RGrfHtZXY9fIjV8x8o ``` -------------------------------- ### Configure HTML Sanitizer Policies Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/htmlSanitizer.adoc Opt into additional OWASP policies with configuration. This example adds the IMAGES policy, allowing image elements and attributes. ```yaml micronaut: security: html-sanitizer: policies: - BLOCKS - FORMATTING - LINKS - IMAGES ``` -------------------------------- ### Example Controller with Secured Expressions Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/secured/securedExpression.adoc Demonstrates how to use expressions within the @Secured annotation to access the authenticated user. The 'user' object is of type Authentication. ```java package example; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.security.annotation.Secured; import io.micronaut.security.authentication.Authentication; @Controller("/expressions") public class ExampleController { @Secured("isAuthenticated() and user.username == 'admin'") @Get("/admin") public String admin() { return "Admin Only"; } @Secured("user.roles.contains('editor')") @Get("/editor") public String editor() { return "Editor Only"; } @Secured("user.claims['customClaim'] == 'someValue'") @Get("/custom") public String custom() { return "Custom Claim Access"; } @Secured("isAuthenticated()") @Get public String index(Authentication user) { return "Hello " + user.getName(); } } ``` -------------------------------- ### Custom AuthenticationProvider Implementation Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationProviders/imperativeAuthenticationProviders.adoc Example of a custom implementation of the `AuthenticationProvider` interface. This is suitable for imperative authentication logic. ```java package io.micronaut.security.docs.blockingauthenticationprovider; import io.micronaut.security.authentication.AuthenticationProvider; import io.micronaut.security.authentication.AuthenticationRequest; import io.micronaut.security.authentication.AuthenticationResponse; import io.micronaut.security.authentication.UserDetails; import io.micronaut.security.authentication.UsernamePasswordCredentials; import io.micronaut.security.authentication.provider.HttpRequestAuthenticationProvider; import io.micronaut.security.authentication.provider.ExecutorAuthenticationProvider; import io.micronaut.security.authentication.provider.HttpRequestExecutorAuthenticationProvider; import io.micronaut.security.authentication.provider.TaskExecutors; import io.micronaut.security.authentication.UsernamePasswordCredentials; import io.micronaut.security.authentication.Authentication; import jakarta.inject.Singleton; import reactor.core.publisher.Mono; @Singleton public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Mono authenticate(AuthenticationRequest authenticationRequest) { if (authenticationRequest instanceof UsernamePasswordCredentials) { UsernamePasswordCredentials creds = (UsernamePasswordCredentials) authenticationRequest; if ("test".equals(creds.getUsername()) && "password".equals(creds.getPassword())) { return Mono.just(new UserDetails(creds.getUsername(), null)); } } return Mono.empty(); } } ``` -------------------------------- ### Configure Google as an OpenID Provider Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth.adoc Example configuration for integrating Google as an OpenID Connect provider. Ensure you replace placeholder values with your actual client ID and secret. ```yaml micronaut: security: oauth2: clients: google: client-secret: <> client-id: <> openid: issuer: https://accounts.google.com ``` -------------------------------- ### Example HTTP Request with CSRF Token Header Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/csrf/csrfTokenResolvers/httpHeaderCsrfTokenResolver.adoc This example demonstrates an HTTP POST request that includes a CSRF token in the 'X-CSRF-TOKEN' header. This is a common pattern for securing web applications against Cross-Site Request Forgery attacks. ```http POST /transfer HTTP/1.1 Host: vulnerable bank Content-Type: application/x-www-form-urlencoded Cookie: session= X-CSRF-TOKEN: o24b65486f506e2cd4403caf0d640024 [...] amount=100&toUser=intended ``` -------------------------------- ### YAML Configuration for Built-in Endpoints Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/builtInEndpointsAccess.adoc Configure security rules for built-in endpoints. This example shows how to secure the /beans endpoint while leaving /info open. ```yaml micronaut: security: endpoints: sensitive: - /beans open: - /info ``` -------------------------------- ### Custom Rejection Handler Implementation Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/rejection.adoc Example of a custom implementation for handling authorization exceptions. This allows for complete control over the response when a request is rejected. ```java package example.security.rejection; import io.micronaut.security.authentication.AuthorizationException; import io.micronaut.security.authentication.AuthorizationExceptionHandler; import io.micronaut.security.config.RedirectConfigurationProperties; import io.micronaut.http.HttpRequest; import io.micronaut.http.HttpResponse; import io.micronaut.http.server.exceptions.ExceptionHandler; import jakarta.inject.Inject; import jakarta.inject.Singleton; @Singleton public class MyRejectionHandler implements AuthorizationExceptionHandler { private final RedirectConfigurationProperties redirectConfiguration; @Inject public MyRejectionHandler(RedirectConfigurationProperties redirectConfiguration) { this.redirectConfiguration = redirectConfiguration; } @Override public HttpResponse handle(HttpRequest request, AuthorizationException type) { // Customize your rejection logic here // For example, return a custom JSON response or redirect return HttpResponse.status(403, "Forbidden"); } } ``` -------------------------------- ### Configure GitHub OAuth 2.0 Client Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/authorization-code/oauth2-authorization-code/oauth2-configuration.adoc Example configuration for integrating with GitHub using OAuth 2.0. Set your client ID, secret, desired scopes, and the authorization and token endpoint URLs. ```yaml micronaut: security: oauth2: clients: github: client-id: <> client-secret: <> scopes: - user:email - read:user authorization: url: https://github.com/login/oauth/authorize token: url: https://github.com/login/oauth/access_token auth-method: client-secret-post ``` -------------------------------- ### Introspection Response Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/tokenendpoints/introspectionendpoint.adoc An example of the JSON response received from the introspection endpoint, indicating the token's active status and associated claims. ```json { "active": false "username": "1234567890", "sub": "1234567890", "name": "John Doe", "admin": true, "jti": "3568c3a3-ae2c-41b3-ac59-54e9185d3eb8", "iat": 1601049598, "exp": 1601053198 } ``` -------------------------------- ### Example POST Request with CSRF Token Field Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/csrf/csrfTokenResolvers/fieldCsrfTokenResolver.adoc This example demonstrates a typical POST request to a banking endpoint, including the CSRF token within the form-url-encoded body. This is the format the FieldCsrfTokenResolver expects. ```http POST /transfer HTTP/1.1 Host: vulnerable bank Content-Type: application/x-www-form-urlencoded Cookie: session= [...] amount=100&toUser=intended&csrfToken=o24b65486f506e2cd4403caf0d640024 ``` -------------------------------- ### YAML Configuration for IP Patterns Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/ipPattern.adoc Configure IP patterns to reject traffic. This example uses IpPatternsRule to reject requests not originating from '127.0.0.1' or the '192.168.1.*' range. ```yaml security: rules: - ipPatterns: allow: - "127.0.0.1" - "192.168.1.*" ``` -------------------------------- ### Publish Micronaut Security Locally Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/CONTRIBUTING.md Run this task to get a local development version of Micronaut security working. You can then reference the version specified with projectVersion in gradle.properties in a test project. ```bash ./gradlew pTML ``` -------------------------------- ### Example JWT Access Token Response Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt/render.adoc This is an example of a typical JSON payload returned for a JWT access token, conforming to RFC 6749. ```json HTTP/1.1 200 OK Content-Type: application/json;charset=UTF-8 Cache-Control: no-store Pragma: no-cache { "access_token":"eyJhbGciOiJIUzI1NiJ9...", "token_type":"Bearer", "expires_in":3600, "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA...", "username": "euler", "roles": [ "ROLE_USER" ] } ``` -------------------------------- ### Client Credentials Configuration Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/clientcredentials/clientecredentialshttpclient.adoc Configure an OAuth 2.0 client to use client credentials flow for token acquisition. This example sets up the 'companyauthserver' client to propagate tokens to the 'inventory' HTTP client. ```yaml micronaut: security: oauth2: clients: companyauthserver: client-id: 'XXX' client-secret: 'YYY' client-credentials: service-id-regex: 'inventory' token: url: "https://foo.bar/token" auth-method: client_secret_basic ``` -------------------------------- ### Example Controller with Jakarta Annotations Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/secured/jakartaAnnotations.adoc This Java controller demonstrates the usage of Jakarta's security annotations to control access to different endpoints. Ensure the Micronaut Security Processor is included in your annotation processor path. ```java package example.security.securityRule.permitall; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.security.annotation.Secured; import jakarta.annotation.security.DenyAll; import jakarta.annotation.security.PermitAll; import jakarta.annotation.security.RolesAllowed; @Controller("/secured") public class ExampleController { @Secured("ROLE_ADMIN") @Get("/admin") public String admin() { return "admin"; } @RolesAllowed({"ROLE_ADMIN", "ROLE_X"}) @Get("/withroles") public String withroles() { return "withroles"; } @PermitAll @Get("/anonymous") public String anonymous() { return "anonymous"; } @DenyAll @Get("/denyall") public String denyall() { return "denyall"; } } ``` -------------------------------- ### Intercept URL Map Configuration Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/interceptUrlMap.adoc Defines access rules for URL patterns and HTTP methods. Use this to specify which requests are allowed for anonymous users, authenticated users, or users with specific roles. ```yaml micronaut: security: intercept-url-map: - pattern: /v1/myResource/** httpMethod: GET access: - isAnonymous() - pattern: /v1/myResource/** access: - isAuthenticated() ``` -------------------------------- ### Session-Based Authentication Configuration (YAML) Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/session.adoc Example configuration for session-based authentication in Micronaut applications. This snippet shows how to enable session authentication and configure redirection URLs. ```yaml micronaut: security: authentication: session redirect: login: "/login" error: "/error" success: "/home" unauthorized: "/unauthorized" ``` -------------------------------- ### OAuth CSRF Filter Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/authorization-code.adoc An example of a server filter to implement CSRF protection for OAuth login endpoints. It compares user-specific state with the value sent in the request to prevent forced login attacks. ```java package io.micronaut.security.oauth2.docs.endpoint; import io.micronaut.http.HttpRequest; import io.micronaut.http.MutableHttpResponse; import io.micronaut.http.filter.HttpServerFilter; import io.micronaut.http.filter.ServerFilterChain; import io.micronaut.security.authentication.AuthenticationFailed; import io.micronaut.security.authentication.AuthenticationProvider; import io.micronaut.security.authentication.UsernamePasswordCredentials; import io.micronaut.security.oauth2.client.OpenIdProviderMetadata; import io.micronaut.security.oauth2.client.OpenIdProviderMetadataResolver; import io.micronaut.security.oauth2.configuration.OauthConfiguration; import io.micronaut.security.oauth2.configuration.OauthConfigurationProperties; import io.micronaut.security.oauth2.endpoint.OauthController; import io.micronaut.security.oauth2.endpoint.OauthControllerConfiguration; import io.micronaut.security.oauth2.endpoint.authorization.state.State; import io.micronaut.security.oauth2.endpoint.authorization.state.StateAwareOpenIdProviderTokenServices; import io.micronaut.security.oauth2.endpoint.authorization.state.StateAwareTokenServices; import io.micronaut.security.oauth2.endpoint.authorization.state.StateProvider; import io.micronaut.security.oauth2.openid.OpenIdProviderDiscoveryClient; import io.micronaut.security.token.Token; import io.micronaut.security.token.TokenResolver; import io.micronaut.security.token.cookie.CookieTokenReader; import io.micronaut.security.token.cookie.CookieTokenWriter; import io.micronaut.security.token.jwt.render.AccessRefreshTokenRenderer; import io.micronaut.security.token.jwt.signature.SignatureGenerator; import io.micronaut.security.token.jwt.signature.SignatureRenderer; import io.micronaut.security.token.jwt.validator.JwtTokenValidator; import io.micronaut.session.Session; import io.micronaut.session.SessionStore; import org.reactivestreams.Publisher; import javax.inject.Inject; import javax.inject.Singleton; import java.util.Optional; @Singleton public class OAuthCsrfFilter implements HttpServerFilter { public static final String OAUTH_STATE_SESSION_KEY = "oauth_state"; private final SessionStore sessionStore; @Inject public OAuthCsrfFilter(SessionStore sessionStore) { this.sessionStore = sessionStore; } @Override public Publisher> doFilter(HttpRequest request, ServerFilterChain chain) { Optional sessionOptional = sessionStore.find(request); if (sessionOptional.isPresent()) { Session session = sessionOptional.get(); String state = request.getParameters().getFirst("state"); if (state != null) { Optional sessionStateOptional = session.get(OAUTH_STATE_SESSION_KEY, String.class); if (sessionStateOptional.isPresent()) { String sessionState = sessionStateOptional.get(); if (!state.equals(sessionState)) { return io.micronaut.runtime.server.HttpServerFilter.rejected(request, "Invalid state parameter"); } session.remove(OAUTH_STATE_SESSION_KEY); } else { return io.micronaut.runtime.server.HttpServerFilter.rejected(request, "Invalid state parameter"); } } } return chain.proceed(request); } } ``` -------------------------------- ### Example End-User Context Attributes JSON Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/ojdbcExtensions/applicationManagedDataRolesAndAttributes/endUserContextAttributes.adoc This JSON object represents the attributes of two end-user context objects, 'user_details' and 'location_info', which can be stored within an authentication attribute. ```json { "app_schema.user_details" : { "first_name" : "George", "last_name" : "Washington" }, "app_schema.location_info" : { "City" : "Mount Vernon", "State" : "Virginia", "Country" : "United States" } } ``` -------------------------------- ### JWT Header Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt.adoc A typical JWT header, which is a base64-encoded JSON object specifying the algorithm and token type. ```json { "alg": "HS256", "typ": "JWT" } ``` -------------------------------- ### Secured Annotation Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/secured.adoc Demonstrates the use of the @Secured annotation to protect controller actions. Authenticated users can access 'authenticated', users with specific roles can access 'withroles', and anonymous users can access 'anonymous'. ```java package example.security.securityRule.secured; import io.micronaut.context.annotation.Requires; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; import io.micronaut.security.annotation.Secured; import io.micronaut.security.rules.SecurityRule; @Requires(property = "spec.security.authentication", value = "true") @Controller("/secured") public class ExampleController { @Secured("isAuthenticated()") @Get("/authenticated") public String authenticated() { return "authenticated"; } @Secured({"ROLE_ADMIN", "ROLE_X"}) @Get("/withroles") public String withroles() { return "withroles"; } @Secured(SecurityRule.IS_ANONYMOUS) @Get("/anonymous") public String anonymous() { return "anonymous"; } } ``` -------------------------------- ### Double Submit Cookie Pattern Example Request Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/csrf/csrfMitigations/doubleSubmitCookiePattern.adoc Illustrates an HTTP POST request demonstrating the Double Submit Cookie pattern. The CSRF token is present in both the Cookie header and the form data. ```http POST /transfer HTTP/1.1 Host: vulnerable bank Content-Type: application/x-www-form-urlencoded Cookie: session=; __Host-csrfToken=o24b65486f506e2cd4403caf0d640024 [...] amount=100&toUser=intended&csrfToken=o24b65486f506e2cd4403caf0d640024 ``` -------------------------------- ### Enable HTTPS and X.509 Client Authentication Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/x509.adoc Sample configuration to enable X.509 support and configure HTTPS with client certificate authentication. Set 'client-authentication' to 'want' or 'need'. ```yaml micronaut: application: name: your_application_name security: x509: enabled: true ssl: enabled: true server: ssl: client-authentication: want # or 'need' key-store: path: classpath:ssl/keystore.p12 password: your_keystore_password type: PKCS12 trust-store: path: classpath:ssl/truststore.jks password: your_truststore_password type: JKS ``` -------------------------------- ### Build Documentation Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/AGENTS.md Generate the project documentation. This task is essential for docs-only changes or to preview documentation updates. ```bash ./gradlew docs ``` -------------------------------- ### GET /token_info Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/tokenendpoints/introspectionendpoint.adoc Access a secured GET endpoint to retrieve the introspection response for the authenticated user. The request requires an Authorization header. ```APIDOC ## GET /token_info ### Description Access a secured GET endpoint to retrieve the introspection response for the authenticated user. The request requires an Authorization header. ### Method GET ### Endpoint /token_info ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash GET /token_info Accept: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6IjM1NjhjM2EzLWFlMmMtNDFiMy1hYzU5LTU0ZTkxODVkM2ViOCIsImlhdCI6MTYwMTA0OTU5OCwiZXhwIjoxNjAxMDUzMTk4fQ.Sc5Xh7jI6e_F3FAUo3n3AUCHNSxWH8t-WlM6JxeHZGI ``` ### Response #### Success Response (200) - **active** (boolean) - Indicates if the token is active. - **username** (string) - The username associated with the token. - **sub** (string) - The subject of the token. - **name** (string) - The name associated with the token. - **admin** (boolean) - Indicates if the user has admin privileges. - **jti** (string) - The JWT ID. - **iat** (integer) - The issued at timestamp. - **exp** (integer) - The expiration timestamp. #### Response Example ```json { "active": false, "username": "1234567890", "sub": "1234567890", "name": "John Doe", "admin": true, "jti": "3568c3a3-ae2c-41b3-ac59-54e9185d3eb8", "iat": 1601049598, "exp": 1601053198 } ``` ``` -------------------------------- ### Introspect Token via GET Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/tokenendpoints/introspectionendpoint.adoc Access a secured GET endpoint to retrieve the introspection response for the authenticated user's token. The token is typically provided in the Authorization header. ```bash GET /token_info Accept: application/json Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6IjM1NjhjM2EzLWFlMmMtNDFiMy1hYzU5LTU0ZTkxODVkM2ViOCIsImlhdCI6MTYwMTA0OTU5OCwiZXhwIjoxNjAxMDUzMTk4fQ.Sc5Xh7jI6e_F3FAUo3n3AUCHNSxWH8t-WlM6JxeHZGI ``` -------------------------------- ### Create Micronaut App with Security Feature Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/security-installation.adoc Use the Micronaut CLI to create a new application with security features pre-configured. ```bash $ mn create-app my-app --features security ``` -------------------------------- ### Add JWT Support via Micronaut CLI Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt.adoc Use the Micronaut CLI to create a new project with JWT support pre-configured. ```bash $ mn create-app my-app --features security-jwt ``` -------------------------------- ### JWT Claims Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt.adoc A typical JWT claims set, which is a base64-encoded JSON object containing information like expiration time, subject, and roles. ```json { "exp": 1422990129, "sub": "jimi", "roles": [ "ROLE_ADMIN", "ROLE_USER" ], "iat": 1422986529 } ``` -------------------------------- ### Run All Checks Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/AGENTS.md Execute all standard checks, including tests, linting, and other quality gates. This provides a comprehensive verification of changes. ```bash ./gradlew check ``` -------------------------------- ### Obtain ClientCredentialsClient Statically Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/clientcredentials/clientCredentailsClientOf.adoc Use this snippet to get a static `ClientCredentialsClient` instance when a Micronaut Application context is not available. This is useful for scenarios outside of a running Micronaut application. ```java io.micronaut.security.oauth2.client.clientcredentials.ClientCredentialsClient ``` -------------------------------- ### Custom SensitiveEndpointRule Implementation Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/builtInEndpointsAccess.adoc Replace the default SensitiveEndpointRule to implement custom logic for authenticated access to sensitive endpoints. This example restricts access to users with the 'admin' role. ```java import io.micronaut.http.HttpRequest import io.micronaut.security.authentication.Authentication import io.micronaut.security.rules.SensitiveEndpointRule import jakarta.inject.Singleton @Singleton class CustomSensitiveEndpointRule implements SensitiveEndpointRule { @Override boolean checkSensitiveAuthenticated(HttpRequest request, Authentication authentication) { return authentication != null && authentication.getAuthorities().contains("admin") } @Override boolean isSensitive(HttpRequest request) { return request.getPath().equals("/beans") } } ``` -------------------------------- ### Run Security Module Tests Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/AGENTS.md Execute tests for the core security module. This is a common verification step for changes within the security module. ```bash ./gradlew :security:test ``` -------------------------------- ### Run Security OAuth2 Module Tests Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/AGENTS.md Execute tests for the security-OAuth2 module. Verify changes related to OAuth2 integration. ```bash ./gradlew :security-oauth2:test ``` -------------------------------- ### Configure JWKS Cache Expiration with Micronaut Cache Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt/jwtValidation/jwks/jwksCache.adoc Configure the expiration time for the 'jwks' cache when using Micronaut Cache. This example sets the expiration to 24 hours. ```yaml micronaut: caches: jwks: expire-after-write: 24h ``` -------------------------------- ### Run Checkstyle for a Module Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/CONTRIBUTING.md Execute Checkstyle for a specific module to ensure code adheres to Micronaut's standards. Replace with the actual module name. ```bash ./gradlew :checkstyleMain ``` -------------------------------- ### Static JWKS Configuration (YAML) Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt/jwtValidation/jwks/staticJwks.adoc Configure the JWKS path using `classpath:` or `file:` prefixes in your application configuration. ```yaml micronaut: security: jwt: jwks: path: classpath:jwks/certs.json ``` -------------------------------- ### Run Test Suite Tests Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/AGENTS.md Execute tests from the main test suite project. This covers cross-module and integration scenarios. ```bash ./gradlew :test-suite:test ``` -------------------------------- ### Custom Authentication to String Converter Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/dataAuditing/identityMapping.adoc Implement a custom `TypeConverter` to map `Authentication` objects to String fields, replacing the default `PrincipalToStringConverter`. This example maps a custom attribute to the identity. ```java package import io.micronaut.core.convert.ConversionContext; import io.micronaut.core.convert.TypeConverter; import io.micronaut.security.authentication.Authentication; import jakarta.inject.Singleton; import java.util.Optional; @Singleton public class AuthenticationToStringConverter implements TypeConverter { @Override public Optional convert(Authentication object, Class targetType, ConversionContext context) { // <1> Conversion between Authentication and String is implemented // <2> The implementation maps a custom attribute to the auto-populated identity return Optional.ofNullable(object.getAttributes().get("custom_attribute")).map(Object::toString); } } ``` -------------------------------- ### RunAs Annotation Example Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/securityFilter/securityRule/runAs.adoc This snippet demonstrates the usage of the @RunAs annotation to specify roles for a method. It's useful for scheduled tasks or methods that delegate to services requiring specific authentication. ```java package example.security; import io.micronaut.http.annotation.Controller; import io.micronaut.security.annotation.RunAs; import io.micronaut.security.annotation.Secured; import io.micronaut.security.rules.SecurityRule; @Controller("/runas") public class RunAsController { @Secured(SecurityRule.IS_AUTHENTICATED) @RunAs("ROLE_ADMIN") public String adminOnly() { return "Admin Content"; } @Secured(SecurityRule.IS_AUTHENTICATED) @RunAs(roles = "ROLE_MANAGER", appendRoles = false) public String managerOnly() { return "Manager Content"; } @Secured(SecurityRule.IS_AUTHENTICATED) @RunAs(roles = {"ROLE_USER", "ROLE_AUDIT"}) public String userAndAudit() { return "User and Audit Content"; } @Secured(SecurityRule.IS_AUTHENTICATED) @RunAs(roles = "ROLE_ADMIN", attributes = {"tenant": "ACME"}) public String adminWithTenant() { return "Admin Content with Tenant"; } @Secured(SecurityRule.IS_AUTHENTICATED) @RunAs(roles = "ROLE_ADMIN", attributes = {"tenant": "ACME"}, appendAttributes = false) public String adminReplaceTenant() { return "Admin Content with new Tenant"; } } ``` -------------------------------- ### Sample HTTP Request to Refresh Access Token Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/tokenendpoints/refresh.adoc Send a POST request to the /oauth/access_token endpoint with grant_type and refresh_token parameters to obtain a new access token. ```bash POST /oauth/access_token HTTP/1.1 Host: micronaut.example Content-Type: application/x-www-form-urlencoded grant_type=refresh_token&refresh_token=eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00ifQ.... ``` -------------------------------- ### Run Geb Firefox Tests Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/test-suite-geb/README.md Execute Geb tests with Firefox by specifying the environment and Gecko driver path. ```bash ./gradlew :test-suite-geb:test -Dgeb.env=firefox -Dwebdriver.gecko.driver=/Users/sdelamo/Applications/geckodriver ``` -------------------------------- ### GitHub User Details Mapper Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/authorization-code/oauth2-authorization-code/oauth2-user-details.adoc Implement the `OauthAuthenticationMapper` to convert GitHub user data into a Micronaut `Authentication` object. This example demonstrates fetching user details using a declarative client and mapping them. ```java package io.micronaut.security.oauth2.docs.github; import io.micronaut.security.authentication.Authentication; import io.micronaut.security.authentication.UsernamePasswordCredentials; import io.micronaut.security.oauth2.endpoint.token.response.TokenResponse; import io.micronaut.security.oauth2.openid.IdToken; import io.micronaut.security.oauth2.response.OauthAuthenticationMapper; import jakarta.inject.Named; import jakarta.inject.Singleton; import java.util.Collections; @Singleton @Named("github") // <1> public class GithubAuthenticationMapper implements OauthAuthenticationMapper { private final GithubApiClient githubApiClient; public GithubAuthenticationMapper(GithubApiClient githubApiClient) { this.githubApiClient = githubApiClient; } @Override public Authentication map(TokenResponse tokenResponse) { GithubUser githubUser = githubApiClient.getUser(tokenResponse); // <3> return Authentication.build(githubUser.getUsername(), Collections.emptyList(), Collections.singletonMap("github", githubUser)); // <4> } @Override public boolean supports(TokenResponse tokenResponse) { return OauthAuthenticationMapper.super.supports(tokenResponse); } } ``` -------------------------------- ### Configure State Persistence to use HTTP Session Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/authorization-code/state.adoc To use HTTP session for state persistence, add the `micronaut-session` dependency and configure `micronaut.security.oauth2.state.persistence` to `session`. ```yaml micronaut.security.oauth2.state.persistence: session ``` -------------------------------- ### cURL Command for Basic Auth Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/basicAuth.adoc Use this cURL command to test basic authentication by sending credentials directly in the URL. ```bash curl "http://localhost:8080/info" \ -u 'user:password' ``` -------------------------------- ### YAML Configuration for Token Propagation Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/tokenPropagation.adoc Configures HttpHeaderTokenPropagator and TokenPropagationHttpClientFilter for seamless security token propagation. ```yaml micronaut: security: token: propagation: enabled: true filter: order: 100 propagator: http-header: enabled: true header-name: "X-Auth-Token" service-id-regex: ".*" ``` -------------------------------- ### Micronaut Data Entity with Auditing Annotations Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/dataAuditing/annotations.adoc Example of a Micronaut Data entity demonstrating the usage of @CreatedBy and @UpdatedBy annotations. The @CreatedBy annotation populates the creator field on save, and @UpdatedBy populates the editor field on save and update. ```java package example.micronaut.security.audit.docs.createdby; import io.micronaut.data.annotation.GeneratedValue; import io.micronaut.data.annotation.Id; import io.micronaut.data.annotation.MappedEntity; import io.micronaut.security.annotation.CreatedBy; import io.micronaut.security.annotation.UpdatedBy; import java.time.Instant; @MappedEntity public class Book { @Id @GeneratedValue private Long id; private String title; @CreatedBy private String creator; @UpdatedBy private String editor; private Instant dateCreated = Instant.now(); public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getCreator() { return creator; } public void setCreator(String creator) { this.creator = creator; } public String getEditor() { return editor; } public void setEditor(String editor) { this.editor = editor; } public Instant getDateCreated() { return dateCreated; } public void setDateCreated(Instant dateCreated) { this.dateCreated = dateCreated; } } ``` -------------------------------- ### Run Security JWT Module Tests Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/AGENTS.md Execute tests for the security-JWT module. Use this to verify changes related to JWT functionality. ```bash ./gradlew :security-jwt:test ``` -------------------------------- ### Configure HTTP Client for JWKS Fetching Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/jwt/jwtValidation/jwks.adoc Configure Micronaut HTTP Client settings to be used when fetching the remote JWK Set. This allows applying HTTP client configurations like proxies. ```yaml micronaut: security: token: jwt: signatures: awscognito: jwks-uri: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxx/.well-known/jwks.json" # Configure the HTTP client to use a proxy for fetching JWKS http-client: proxy-address: "http://localhost:8080" ``` -------------------------------- ### Custom User Class with Email Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/retrievingAuthenticatedUser/customAuthenticatedUser.adoc Define a custom class to hold authenticated user information, including an email address. ```java package io.micronaut.security.docs.customauthentication; import io.micronaut.security.authentication.UserInfo; import java.util.Map; public class AuthenticationWithEmail extends UserInfo { public AuthenticationWithEmail(Map attributes) { super(attributes); } public String getEmail() { return (String) getAttributes().get("email"); } } ``` -------------------------------- ### GitHub API Client Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/oauth/flows/authorization-code/oauth2-authorization-code/oauth2-user-details.adoc Create a declarative HTTP client to fetch user details from GitHub. ```java package io.micronaut.security.oauth2.docs.github; import io.micronaut.http.annotation.Get; import io.micronaut.http.client.annotation.Client; import io.micronaut.security.oauth2.client.clientcredentials.ClientCredentialsAccessTokenProvider; import io.micronaut.security.oauth2.client.clientcredentials.ClientCredentialsOAuthClient; import io.micronaut.security.oauth2.configuration.OauthClientConfiguration; import io.micronaut.security.oauth2.endpoint.token.response.TokenResponse; import jakarta.inject.Singleton; @Client("${oauth.github.client.id}") // <2> public interface GithubApiClient extends ClientCredentialsOAuthClient { @Override default OauthClientConfiguration getOauthClientConfiguration() { return null; } @Override default ClientCredentialsAccessTokenProvider getAccessTokenProvider() { return null; } @Get("/user") GithubUser getUser(TokenResponse tokenResponse); } ``` -------------------------------- ### Add Session Security Feature via CLI Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/authenticationStrategies/session.adoc Use the Micronaut CLI to add the `security-session` feature to your project for session security. ```bash $ mn create-app my-app --features security-session ``` -------------------------------- ### POST /token_info Source: https://github.com/micronaut-projects/micronaut-security/blob/5.3.x/src/main/docs/guide/tokenendpoints/introspectionendpoint.adoc Introspect a token by sending a POST request with the token and optionally a token type hint. The request should include appropriate Authorization and Content-Type headers. ```APIDOC ## POST /token_info ### Description Introspect a token by sending a POST request with the token and optionally a token type hint. The request should include appropriate Authorization and Content-Type headers. ### Method POST ### Endpoint /token_info ### Parameters #### Query Parameters - **token** (string) - Required - The token to introspect. - **token_type_hint** (string) - Optional - A hint about the type of the token (e.g., 'access_token'). #### Request Body This endpoint uses `application/x-www-form-urlencoded` content type. ### Request Example ```bash POST /token_info Accept: application/json Content-Type: application/x-www-form-urlencoded Authorization: Basic dXNlcjpwYXNzd29yZA== token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImp0aSI6IjM1NjhjM2EzLWFlMmMtNDFiMy1hYzU5LTU0ZTkxODVkM2ViOCIsImlhdCI6MTYwMTA0OTU5OCwiZXhwIjoxNjAxMDUzMTk4fQ.Sc5Xh7jI6e_F3FAUo3n3AUCHNSxWH8t-WlM6JxeHZGI&token_type_hint=access_token ``` ### Response #### Success Response (200) - **active** (boolean) - Indicates if the token is active. - **username** (string) - The username associated with the token. - **sub** (string) - The subject of the token. - **name** (string) - The name associated with the token. - **admin** (boolean) - Indicates if the user has admin privileges. - **jti** (string) - The JWT ID. - **iat** (integer) - The issued at timestamp. - **exp** (integer) - The expiration timestamp. #### Response Example ```json { "active": false, "username": "1234567890", "sub": "1234567890", "name": "John Doe", "admin": true, "jti": "3568c3a3-ae2c-41b3-ac59-54e9185d3eb8", "iat": 1601049598, "exp": 1601053198 } ``` ```