agentskills.codes
SP

spring-authorization-server

|

Install

mkdir -p .claude/skills/spring-authorization-server && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/13452" && unzip -o skill.zip -d .claude/skills/spring-authorization-server && rm skill.zip

Installs to .claude/skills/spring-authorization-server

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Spring Authorization Server for building OAuth 2.1 and OpenID Connect providers. USE WHEN: user mentions "OAuth2 server", "authorization server", "OIDC provider", "token endpoint", asks about "how to implement OAuth2", "create authorization server", "issue JWT tokens", "custom OAuth provider" DO NOT USE FOR: OAuth2 client configuration - use `spring-security` instead, resource server JWT validation - use `spring-security` instead
433 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)

About this skill

Spring Authorization Server - Quick Reference

Full Reference: See advanced.md for JPA client persistence, JWT configuration, custom token claims, user info endpoint, consent controller, token revocation, resource server integration, and testing.

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: spring-authorization-server for comprehensive documentation.

Dependencies

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-authorization-server</artifactId>
</dependency>

OAuth 2.1 Flows

Authorization Code + PKCE:

Client ──(1) Authorization Request + code_challenge──▶ Auth Server
      ◀──(2) Authorization Code──────────────────────
      ──(3) Token Request + code_verifier────────────▶
      ◀──(4) Access Token + Refresh Token + ID Token─

Basic Configuration

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    @Order(1)
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
            throws Exception {
        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

        http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
            .oidc(Customizer.withDefaults());  // Enable OpenID Connect

        http.exceptionHandling(exceptions -> exceptions
                .defaultAuthenticationEntryPointFor(
                    new LoginUrlAuthenticationEntryPoint("/login"),
                    new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
                )
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()));

        return http.build();
    }

    @Bean
    @Order(2)
    public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(authorize -> authorize.anyRequest().authenticated())
            .formLogin(Customizer.withDefaults());
        return http.build();
    }
}

Client Registration

@Bean
public RegisteredClientRepository registeredClientRepository() {
    RegisteredClient webClient = RegisteredClient.withId(UUID.randomUUID().toString())
        .clientId("web-client")
        .clientSecret("{noop}secret")
        .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
        .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
        .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
        .redirectUri("http://localhost:8080/login/oauth2/code/web-client")
        .scope(OidcScopes.OPENID)
        .scope(OidcScopes.PROFILE)
        .scope("read")
        .clientSettings(ClientSettings.builder()
            .requireAuthorizationConsent(true)
            .requireProofKey(true)  // PKCE required
            .build())
        .tokenSettings(TokenSettings.builder()
            .accessTokenTimeToLive(Duration.ofMinutes(15))
            .refreshTokenTimeToLive(Duration.ofDays(7))
            .reuseRefreshTokens(false)
            .build())
        .build();

    return new InMemoryRegisteredClientRepository(webClient);
}

Best Practices

DoDon't
Require PKCE for public clientsAllow plain authorization code
Use short-lived access tokensLong-lived access tokens
Rotate refresh tokensReuse refresh tokens indefinitely
Store keys securely (Vault)Hardcode keys in config
Validate redirect URIs strictlyAllow open redirects

When NOT to Use This Skill

  • OAuth2 Client Configuration - Use spring-security
  • Resource Server - For validating JWT tokens use spring-security
  • Basic Authentication - Use spring-security
  • Session Management - Use spring-session

Anti-Patterns

Anti-PatternWhy It's BadBetter Approach
Reusing refresh tokensSecurity risk if compromisedRotate on each use
Long-lived access tokensIncreased exposure windowKeep to 15-30 min
Hardcoded client secretsSecrets in version controlUse secret management
No PKCE for SPAsCode interception vulnerabilityAlways require PKCE
Wildcard redirect URIsOpen redirect vulnerabilityWhitelist exact URIs

Quick Troubleshooting

IssuePossible CauseSolution
401 at /oauth2/authorizeUser not authenticatedCheck SecurityFilterChain order
Invalid client errorClient not registeredVerify RegisteredClientRepository
JWKS endpoint 404JWKSource bean missingEnsure JWKSource configured
Token validation failsIssuer mismatchCheck issuer URL matches
PKCE validation failscode_verifier mismatchVerify PKCE implementation

Production Checklist

  • HTTPS everywhere
  • RSA keys in secure storage
  • Client secrets encrypted
  • PKCE required for public clients
  • Token lifetimes configured
  • Consent flow implemented
  • Token revocation working
  • Rate limiting enabled
  • Audit logging configured

Reference Documentation

Search skills

Search the agent skills registry