├── docs └── manual │ ├── src │ └── docs │ │ └── asciidoc │ │ ├── css │ │ └── style.css │ │ └── index.adoc │ └── spring-security-oauth2-authorization-server-docs-manual.gradle ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── dependency-management.gradle ├── gradle.properties ├── scripts ├── update-dependencies.sh └── release │ ├── wait-for-done.sh │ └── release-notes-sections.yml ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.md │ └── bug_report.md └── workflows │ ├── pr-build-workflow.yml │ └── continuous-integration-workflow.yml ├── etc ├── nohttp │ └── allowlist.lines └── checkstyle │ ├── header.txt │ ├── suppressions.xml │ └── checkstyle.xml ├── samples ├── default-authorizationserver │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── application.yml │ │ │ └── java │ │ │ └── sample │ │ │ ├── DefaultAuthorizationServerApplication.java │ │ │ ├── config │ │ │ └── DefaultSecurityConfig.java │ │ │ └── jose │ │ │ ├── Jwks.java │ │ │ └── KeyGeneratorUtils.java │ └── samples-default-authorizationserver.gradle ├── custom-consent-authorizationserver │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── application.yml │ │ │ └── java │ │ │ └── sample │ │ │ ├── CustomConsentAuthorizationServerApplication.java │ │ │ ├── config │ │ │ └── DefaultSecurityConfig.java │ │ │ └── jose │ │ │ ├── Jwks.java │ │ │ └── KeyGeneratorUtils.java │ └── samples-custom-consent-authorizationserver.gradle ├── messages-resource │ ├── samples-messages-resource.gradle │ └── src │ │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── sample │ │ ├── web │ │ └── MessagesController.java │ │ ├── MessagesResourceApplication.java │ │ └── config │ │ └── ResourceServerConfig.java ├── messages-client │ ├── samples-messages-client.gradle │ └── src │ │ └── main │ │ ├── java │ │ └── sample │ │ │ ├── MessagesClientApplication.java │ │ │ ├── web │ │ │ ├── DefaultController.java │ │ │ └── AuthorizationController.java │ │ │ └── config │ │ │ ├── SecurityConfig.java │ │ │ └── WebClientConfig.java │ │ └── resources │ │ ├── application.yml │ │ └── templates │ │ └── index.html └── README.adoc ├── oauth2-authorization-server ├── src │ ├── test │ │ ├── resources │ │ │ └── org │ │ │ │ └── springframework │ │ │ │ └── security │ │ │ │ └── oauth2 │ │ │ │ └── server │ │ │ │ └── authorization │ │ │ │ ├── custom-oauth2-authorization-consent-schema.sql │ │ │ │ ├── client │ │ │ │ └── custom-oauth2-registered-client-schema.sql │ │ │ │ └── custom-oauth2-authorization-schema.sql │ │ └── java │ │ │ └── org │ │ │ └── springframework │ │ │ └── security │ │ │ ├── oauth2 │ │ │ ├── jwt │ │ │ │ ├── TestJwtClaimsSets.java │ │ │ │ └── TestJoseHeaders.java │ │ │ ├── server │ │ │ │ └── authorization │ │ │ │ │ ├── jackson2 │ │ │ │ │ ├── TestingAuthenticationTokenMixin.java │ │ │ │ │ └── OAuth2AuthorizationServerJackson2ModuleTests.java │ │ │ │ │ ├── config │ │ │ │ │ └── ClientSettingsTests.java │ │ │ │ │ ├── oidc │ │ │ │ │ └── authentication │ │ │ │ │ │ └── OidcUserInfoAuthenticationTokenTests.java │ │ │ │ │ ├── client │ │ │ │ │ └── TestRegisteredClients.java │ │ │ │ │ └── authentication │ │ │ │ │ └── OAuth2RefreshTokenAuthenticationTokenTests.java │ │ │ └── jose │ │ │ │ └── TestJwks.java │ │ │ └── config │ │ │ ├── test │ │ │ └── SpringTestRule.java │ │ │ ├── annotation │ │ │ └── web │ │ │ │ └── configuration │ │ │ │ └── OAuth2AuthorizationServerConfigurationTests.java │ │ │ └── util │ │ │ ├── InMemoryXmlWebApplicationContext.java │ │ │ └── InMemoryXmlApplicationContext.java │ └── main │ │ ├── resources │ │ └── org │ │ │ └── springframework │ │ │ └── security │ │ │ └── oauth2 │ │ │ └── server │ │ │ └── authorization │ │ │ ├── oauth2-authorization-consent-schema.sql │ │ │ ├── client │ │ │ └── oauth2-registered-client-schema.sql │ │ │ └── oauth2-authorization-schema.sql │ │ └── java │ │ └── org │ │ └── springframework │ │ └── security │ │ ├── oauth2 │ │ ├── server │ │ │ └── authorization │ │ │ │ ├── jackson2 │ │ │ │ ├── HashSetMixin.java │ │ │ │ ├── SignatureAlgorithmMixin.java │ │ │ │ ├── UnmodifiableMapMixin.java │ │ │ │ ├── DurationMixin.java │ │ │ │ ├── OAuth2AuthorizationRequestMixin.java │ │ │ │ ├── UnmodifiableMapDeserializer.java │ │ │ │ ├── JsonNodeUtils.java │ │ │ │ └── OAuth2AuthorizationServerJackson2Module.java │ │ │ │ ├── OAuth2TokenCustomizer.java │ │ │ │ ├── web │ │ │ │ ├── OAuth2EndpointUtils.java │ │ │ │ └── authentication │ │ │ │ │ ├── DelegatingAuthenticationConverter.java │ │ │ │ │ ├── OAuth2EndpointUtils.java │ │ │ │ │ └── PublicClientAuthenticationConverter.java │ │ │ │ ├── client │ │ │ │ └── RegisteredClientRepository.java │ │ │ │ ├── OAuth2AuthorizationConsentService.java │ │ │ │ ├── OAuth2AuthorizationService.java │ │ │ │ ├── authentication │ │ │ │ ├── OAuth2ClientCredentialsAuthenticationToken.java │ │ │ │ ├── OAuth2AuthorizationCodeAuthenticationToken.java │ │ │ │ ├── OAuth2RefreshTokenAuthenticationToken.java │ │ │ │ ├── OAuth2AuthenticationProviderUtils.java │ │ │ │ ├── OAuth2AuthorizationCodeRequestAuthenticationException.java │ │ │ │ ├── OAuth2AuthorizationGrantAuthenticationToken.java │ │ │ │ └── OAuth2TokenRevocationAuthenticationToken.java │ │ │ │ └── oidc │ │ │ │ └── authentication │ │ │ │ ├── OidcAuthenticationProviderUtils.java │ │ │ │ ├── JwtUtils.java │ │ │ │ └── OidcUserInfoAuthenticationToken.java │ │ ├── core │ │ │ ├── Version.java │ │ │ ├── OAuth2AuthorizationCode.java │ │ │ ├── authentication │ │ │ │ ├── OAuth2AuthenticationValidator.java │ │ │ │ └── OAuth2AuthenticationContext.java │ │ │ ├── oidc │ │ │ │ ├── OidcProviderMetadataClaimNames.java │ │ │ │ ├── OidcProviderMetadataClaimAccessor.java │ │ │ │ ├── http │ │ │ │ │ └── converter │ │ │ │ │ │ └── HttpMessageConverters.java │ │ │ │ └── OidcClientMetadataClaimNames.java │ │ │ ├── context │ │ │ │ └── Context.java │ │ │ ├── OAuth2TokenType.java │ │ │ ├── OAuth2AuthorizationServerMetadata.java │ │ │ ├── OAuth2TokenIntrospectionClaimNames.java │ │ │ └── OAuth2AuthorizationServerMetadataClaimNames.java │ │ └── jwt │ │ │ ├── JwtEncodingException.java │ │ │ └── JwtEncoder.java │ │ └── config │ │ └── annotation │ │ └── web │ │ ├── configurers │ │ └── oauth2 │ │ │ └── server │ │ │ └── authorization │ │ │ └── AbstractOAuth2Configurer.java │ │ └── configuration │ │ └── RegisterMissingBeanPostProcessor.java └── spring-security-oauth2-authorization-server.gradle ├── .editorconfig ├── .gitignore ├── settings.gradle ├── SUPPORT_POLICY.adoc ├── CODE_OF_CONDUCT.adoc └── gradlew.bat /docs/manual/src/docs/asciidoc/css/style.css: -------------------------------------------------------------------------------- 1 | @import 'spring.css'; 2 | 3 | a code { 4 | color: #097dff; 5 | } 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jgrandja/spring-authorization-server/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=0.2.1-SNAPSHOT 2 | springBootVersion=2.5.3 3 | org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError 4 | org.gradle.parallel=true 5 | org.gradle.caching=true 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /scripts/update-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | rm -f build/updates.txt 3 | ./gradlew dependencyUpdate -Drevision=release 4 | find . -name report.txt | xargs cat > build/updates.txt 5 | echo "Updates...." 6 | cat build/updates.txt | fgrep ' ->' | sort | uniq 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Community Support 4 | url: https://stackoverflow.com/questions/tagged/spring-security 5 | about: Please ask and answer questions on StackOverflow with the tag `spring-security`. 6 | -------------------------------------------------------------------------------- /scripts/release/wait-for-done.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | VERSION=$1 4 | until http -h --check-status --ignore-stdin https://repo1.maven.org/maven2/org/springframework/security/spring-security-oauth2-authorization-server/$VERSION/; do sleep 10; clear; done; spd-say "It is now uploaded" 5 | -------------------------------------------------------------------------------- /etc/nohttp/allowlist.lines: -------------------------------------------------------------------------------- 1 | ^http://[^/]*nabble.com.* 2 | ^http://blog.opensecurityresearch.com/.* 3 | ^http://iharder.sourceforge.net/current/java/base64/ 4 | ^http://jaspan.com.* 5 | ^http://lists.webappsec.org/.* 6 | ^http://webblaze.cs.berkeley.edu/.* 7 | ^http://www.w3.org/2000/09/xmldsig.* 8 | -------------------------------------------------------------------------------- /samples/default-authorizationserver/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9000 3 | 4 | logging: 5 | level: 6 | root: INFO 7 | org.springframework.web: INFO 8 | org.springframework.security: INFO 9 | org.springframework.security.oauth2: INFO 10 | # org.springframework.boot.autoconfigure: DEBUG 11 | -------------------------------------------------------------------------------- /samples/custom-consent-authorizationserver/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 9000 3 | 4 | logging: 5 | level: 6 | root: INFO 7 | org.springframework.web: INFO 8 | org.springframework.security: INFO 9 | org.springframework.security.oauth2: INFO 10 | # org.springframework.boot.autoconfigure: DEBUG 11 | -------------------------------------------------------------------------------- /samples/messages-resource/samples-messages-resource.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'io.spring.convention.spring-sample-boot' 2 | 3 | dependencies { 4 | compile 'org.springframework.boot:spring-boot-starter-web' 5 | compile 'org.springframework.boot:spring-boot-starter-security' 6 | compile 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' 7 | } 8 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/resources/org/springframework/security/oauth2/server/authorization/custom-oauth2-authorization-consent-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE oauth2AuthorizationConsent ( 2 | registeredClientId varchar(100) NOT NULL, 3 | principalName varchar(200) NOT NULL, 4 | authorities varchar(1000) NOT NULL, 5 | PRIMARY KEY (registeredClientId, principalName) 6 | ); 7 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/resources/org/springframework/security/oauth2/server/authorization/oauth2-authorization-consent-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE oauth2_authorization_consent ( 2 | registered_client_id varchar(100) NOT NULL, 3 | principal_name varchar(200) NOT NULL, 4 | authorities varchar(1000) NOT NULL, 5 | PRIMARY KEY (registered_client_id, principal_name) 6 | ); 7 | -------------------------------------------------------------------------------- /docs/manual/src/docs/asciidoc/index.adoc: -------------------------------------------------------------------------------- 1 | = Spring Authorization Server Reference 2 | Joe Grandja 3 | :include-dir: _includes 4 | :security-api-url: https://docs.spring.io/spring-authorization-server/site/docs/current/api/ 5 | :source-indent: 0 6 | :tabsize: 4 7 | :toc: left 8 | 9 | == Preface 10 | 11 | #TODO:# Document preface 12 | 13 | == Introduction 14 | 15 | #TODO:# Document introduction 16 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | max_line_length = 120 8 | 9 | [*.{java,xml}] 10 | indent_style = tab 11 | indent_size = 4 12 | charset = utf-8 13 | continuation_indent_size = 8 14 | 15 | ij_smart_tabs = false 16 | ij_java_align_multiline_parameters = false 17 | 18 | [*.gradle] 19 | indent_style = tab 20 | -------------------------------------------------------------------------------- /samples/messages-resource/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8090 3 | 4 | logging: 5 | level: 6 | root: INFO 7 | org.springframework.web: INFO 8 | org.springframework.security: INFO 9 | org.springframework.security.oauth2: INFO 10 | # org.springframework.boot.autoconfigure: DEBUG 11 | 12 | spring: 13 | security: 14 | oauth2: 15 | resourceserver: 16 | jwt: 17 | issuer-uri: http://auth-server:9000 18 | -------------------------------------------------------------------------------- /scripts/release/release-notes-sections.yml: -------------------------------------------------------------------------------- 1 | releasenotes: 2 | sections: 3 | - title: "New Features" 4 | emoji: ":star:" 5 | labels: ["enhancement"] 6 | - title: "Bug Fixes" 7 | emoji: ":beetle:" 8 | labels: ["bug", "regression"] 9 | - title: "Dependency Upgrades" 10 | emoji: ":hammer:" 11 | labels: ["dependency-upgrade"] 12 | - title: "Non-passive" 13 | emoji: ":rewind:" 14 | labels: ["breaks-passivity"] 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: 'type: enhancement' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Expected Behavior** 11 | 12 | 13 | **Current Behavior** 14 | 15 | 16 | **Context** 17 | 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | build/ 3 | !gradle/wrapper/gradle-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | bin/ 7 | classes/ 8 | target/ 9 | *.log 10 | *.log.* 11 | 12 | ### STS ### 13 | .apt_generated 14 | .classpath 15 | .factorypath 16 | .project 17 | .settings 18 | .springBeans 19 | .sts4-cache 20 | 21 | ### IntelliJ IDEA ### 22 | .idea 23 | *.iws 24 | *.iml 25 | *.ipr 26 | out/ 27 | 28 | ### NetBeans ### 29 | /nbproject/private/ 30 | /nbbuild/ 31 | /dist/ 32 | /nbdist/ 33 | /.nb-gradle/ 34 | 35 | ### VS Code ### 36 | .vscode/ 37 | 38 | ### Mac ### 39 | .DS_Store 40 | -------------------------------------------------------------------------------- /samples/custom-consent-authorizationserver/samples-custom-consent-authorizationserver.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'io.spring.convention.spring-sample-boot' 2 | 3 | dependencies { 4 | compile 'org.springframework.boot:spring-boot-starter-web' 5 | compile 'org.springframework.boot:spring-boot-starter-thymeleaf' 6 | compile 'org.springframework.boot:spring-boot-starter-security' 7 | compile project(':spring-security-oauth2-authorization-server') 8 | 9 | testCompile 'org.springframework.boot:spring-boot-starter-test' 10 | testCompile 'org.springframework.security:spring-security-test' 11 | testCompile 'net.sourceforge.htmlunit:htmlunit' 12 | } 13 | -------------------------------------------------------------------------------- /.github/workflows/pr-build-workflow.yml: -------------------------------------------------------------------------------- 1 | name: PR build 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | name: Build 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ubuntu-latest, macos-latest, windows-latest] 15 | jdk: [8,11,12] 16 | fail-fast: false 17 | steps: 18 | - uses: actions/checkout@v2 19 | - name: Set up JDK ${{ matrix.jdk }} 20 | uses: actions/setup-java@v1 21 | with: 22 | java-version: ${{ matrix.jdk }} 23 | - name: Build with Gradle 24 | run: ./gradlew clean build 25 | -------------------------------------------------------------------------------- /samples/default-authorizationserver/samples-default-authorizationserver.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'io.spring.convention.spring-sample-boot' 2 | 3 | dependencies { 4 | compile 'org.springframework.boot:spring-boot-starter-web' 5 | compile 'org.springframework.boot:spring-boot-starter-security' 6 | compile 'org.springframework.boot:spring-boot-starter-jdbc' 7 | compile project(':spring-security-oauth2-authorization-server') 8 | runtimeOnly 'com.h2database:h2' 9 | 10 | testCompile 'org.springframework.boot:spring-boot-starter-test' 11 | testCompile 'org.springframework.security:spring-security-test' 12 | testCompile 'net.sourceforge.htmlunit:htmlunit' 13 | } 14 | -------------------------------------------------------------------------------- /samples/messages-client/samples-messages-client.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'io.spring.convention.spring-sample-boot' 2 | 3 | dependencies { 4 | compile 'org.springframework.boot:spring-boot-starter-web' 5 | compile 'org.springframework.boot:spring-boot-starter-thymeleaf' 6 | compile 'org.springframework.boot:spring-boot-starter-security' 7 | compile 'org.springframework.boot:spring-boot-starter-oauth2-client' 8 | compile 'org.springframework:spring-webflux' 9 | compile 'io.projectreactor.netty:reactor-netty' 10 | compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' 11 | compile 'org.webjars:webjars-locator-core' 12 | compile 'org.webjars:bootstrap:3.4.1' 13 | compile 'org.webjars:jquery:3.4.1' 14 | } 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: 'type: bug' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | 16 | **Expected behavior** 17 | A clear and concise description of what you expected to happen. 18 | 19 | **Sample** 20 | 21 | A link to a GitHub repository with a [minimal, reproducible sample](https://stackoverflow.com/help/minimal-reproducible-example). 22 | 23 | Reports that include a sample will take priority over reports that do not. 24 | At times, we may require a sample, so it is good to try and include a sample up front. 25 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/resources/org/springframework/security/oauth2/server/authorization/client/custom-oauth2-registered-client-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE oauth2RegisteredClient ( 2 | id varchar(100) NOT NULL, 3 | clientId varchar(100) NOT NULL, 4 | clientIdIssuedAt timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, 5 | clientSecret varchar(200) DEFAULT NULL, 6 | clientSecretExpiresAt timestamp DEFAULT NULL, 7 | clientName varchar(200) NOT NULL, 8 | clientAuthenticationMethods varchar(1000) NOT NULL, 9 | authorizationGrantTypes varchar(1000) NOT NULL, 10 | redirectUris varchar(1000) DEFAULT NULL, 11 | scopes varchar(1000) NOT NULL, 12 | clientSettings varchar(2000) NOT NULL, 13 | tokenSettings varchar(2000) NOT NULL, 14 | PRIMARY KEY (id) 15 | ); 16 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/resources/org/springframework/security/oauth2/server/authorization/client/oauth2-registered-client-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE oauth2_registered_client ( 2 | id varchar(100) NOT NULL, 3 | client_id varchar(100) NOT NULL, 4 | client_id_issued_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL, 5 | client_secret varchar(200) DEFAULT NULL, 6 | client_secret_expires_at timestamp DEFAULT NULL, 7 | client_name varchar(200) NOT NULL, 8 | client_authentication_methods varchar(1000) NOT NULL, 9 | authorization_grant_types varchar(1000) NOT NULL, 10 | redirect_uris varchar(1000) DEFAULT NULL, 11 | scopes varchar(1000) NOT NULL, 12 | client_settings varchar(2000) NOT NULL, 13 | token_settings varchar(2000) NOT NULL, 14 | PRIMARY KEY (id) 15 | ); 16 | -------------------------------------------------------------------------------- /etc/checkstyle/header.txt: -------------------------------------------------------------------------------- 1 | ^\Q/*\E$ 2 | ^\Q * Copyright\E (\d{4}(\-\d{4})? the original author or authors\.|(\d{4}, )*(\d{4}) Acegi Technology Pty Limited)$ 3 | ^\Q *\E$ 4 | ^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$ 5 | ^\Q * you may not use this file except in compliance with the License.\E$ 6 | ^\Q * You may obtain a copy of the License at\E$ 7 | ^\Q *\E$ 8 | ^\Q * https://www.apache.org/licenses/LICENSE-2.0\E$ 9 | ^\Q *\E$ 10 | ^\Q * Unless required by applicable law or agreed to in writing, software\E$ 11 | ^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$ 12 | ^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$ 13 | ^\Q * See the License for the specific language governing permissions and\E$ 14 | ^\Q * limitations under the License.\E$ 15 | ^\Q */\E$ 16 | ^.*$ 17 | -------------------------------------------------------------------------------- /samples/README.adoc: -------------------------------------------------------------------------------- 1 | = Messages Sample 2 | 3 | This sample integrates `spring-security-oauth2-client` and `spring-security-oauth2-resource-server` with *Spring Authorization Server*. 4 | 5 | The username is `user1` and the password is `password`. 6 | 7 | == Run the Sample 8 | 9 | * Run Authorization Server -> `./gradlew -b samples/default-authorizationserver/samples-default-authorizationserver.gradle bootRun` 10 | ** *IMPORTANT:* Make sure to modify your `/etc/hosts` file to avoid problems with session cookie overwrites between `messages-client` and `default-authorizationserver`. Simply add the entry `127.0.0.1 auth-server` 11 | * Run Resource Server -> `./gradlew -b samples/messages-resource/samples-messages-resource.gradle bootRun` 12 | * Run Client -> `./gradlew -b samples/messages-client/samples-messages-client.gradle bootRun` 13 | * Go to `http://127.0.0.1:8080` 14 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven { url 'https://repo.spring.io/plugins-release' } 5 | } 6 | } 7 | 8 | plugins { 9 | id "com.gradle.enterprise" version "3.5.1" 10 | id "io.spring.ge.conventions" version "0.0.7" 11 | } 12 | 13 | rootProject.name = 'spring-authorization-server' 14 | 15 | FileTree buildFiles = fileTree(rootDir) { 16 | include '**/*.gradle' 17 | exclude 'build', '**/gradle', 'settings.gradle', 'buildSrc', '/build.gradle', '.*', 'out' 18 | } 19 | 20 | buildFiles.each { File buildFile -> 21 | String projectName = buildFile.name.replace('.gradle', ''); 22 | String projectPath = ':' + projectName; 23 | include projectPath 24 | def project = findProject("${projectPath}") 25 | project.name = projectName 26 | project.projectDir = buildFile.parentFile 27 | project.buildFileName = buildFile.name 28 | } 29 | -------------------------------------------------------------------------------- /etc/checkstyle/suppressions.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/java/sample/MessagesClientApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | 21 | /** 22 | * @author Joe Grandja 23 | * @since 0.0.1 24 | */ 25 | @SpringBootApplication 26 | public class MessagesClientApplication { 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(MessagesClientApplication.class, args); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /samples/messages-resource/src/main/java/sample/web/MessagesController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.web; 17 | 18 | import org.springframework.web.bind.annotation.GetMapping; 19 | import org.springframework.web.bind.annotation.RestController; 20 | 21 | /** 22 | * @author Joe Grandja 23 | * @since 0.0.1 24 | */ 25 | @RestController 26 | public class MessagesController { 27 | 28 | @GetMapping("/messages") 29 | public String[] getMessages() { 30 | return new String[] {"Message 1", "Message 2", "Message 3"}; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /samples/messages-resource/src/main/java/sample/MessagesResourceApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | 21 | /** 22 | * @author Joe Grandja 23 | * @since 0.0.1 24 | */ 25 | @SpringBootApplication 26 | public class MessagesResourceApplication { 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(MessagesResourceApplication.class, args); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/java/sample/web/DefaultController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.web; 17 | 18 | import org.springframework.stereotype.Controller; 19 | import org.springframework.web.bind.annotation.GetMapping; 20 | 21 | /** 22 | * @author Joe Grandja 23 | * @since 0.0.1 24 | */ 25 | @Controller 26 | public class DefaultController { 27 | 28 | @GetMapping("/") 29 | public String root() { 30 | return "redirect:/index"; 31 | } 32 | 33 | @GetMapping("/index") 34 | public String index() { 35 | return "index"; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /oauth2-authorization-server/spring-security-oauth2-authorization-server.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'io.spring.convention.spring-module' 2 | 3 | dependencies { 4 | compile 'org.springframework.security:spring-security-config' 5 | compile 'org.springframework.security:spring-security-web' 6 | compile 'org.springframework.security:spring-security-oauth2-core' 7 | compile 'org.springframework.security:spring-security-oauth2-jose' 8 | compile 'org.springframework.security:spring-security-oauth2-resource-server' 9 | compile springCoreDependency 10 | compile 'com.nimbusds:nimbus-jose-jwt' 11 | compile 'com.fasterxml.jackson.core:jackson-databind' 12 | 13 | optional 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' 14 | optional 'org.springframework:spring-jdbc' 15 | 16 | testCompile 'org.springframework.security:spring-security-test' 17 | testCompile 'org.springframework:spring-webmvc' 18 | testCompile 'junit:junit' 19 | testCompile 'org.assertj:assertj-core' 20 | testCompile 'org.mockito:mockito-core' 21 | testCompile 'com.jayway.jsonpath:json-path' 22 | 23 | testRuntime 'org.hsqldb:hsqldb' 24 | 25 | provided 'javax.servlet:javax.servlet-api' 26 | } 27 | 28 | jacoco { 29 | toolVersion = '0.8.6' 30 | } 31 | -------------------------------------------------------------------------------- /samples/default-authorizationserver/src/main/java/sample/DefaultAuthorizationServerApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | 21 | /** 22 | * @author Joe Grandja 23 | * @since 0.0.1 24 | */ 25 | @SpringBootApplication 26 | public class DefaultAuthorizationServerApplication { 27 | 28 | public static void main(String[] args) { 29 | SpringApplication.run(DefaultAuthorizationServerApplication.class, args); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /samples/custom-consent-authorizationserver/src/main/java/sample/CustomConsentAuthorizationServerApplication.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample; 17 | 18 | import org.springframework.boot.SpringApplication; 19 | import org.springframework.boot.autoconfigure.SpringBootApplication; 20 | 21 | /** 22 | * @author Daniel Garnier-Moiroux 23 | */ 24 | @SpringBootApplication 25 | public class CustomConsentAuthorizationServerApplication { 26 | 27 | public static void main(String[] args) { 28 | SpringApplication.run(CustomConsentAuthorizationServerApplication.class, args); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /docs/manual/spring-security-oauth2-authorization-server-docs-manual.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'io.spring.convention.docs' 2 | apply plugin: 'io.spring.convention.springdependencymangement' 3 | apply plugin: 'io.spring.convention.dependency-set' 4 | apply plugin: 'io.spring.convention.repository' 5 | apply plugin: 'java' 6 | 7 | asciidoctor { 8 | attributes([stylesheet: 'css/style.css']) 9 | resources { 10 | from(sourceDir) { 11 | include "css/**" 12 | } 13 | } 14 | } 15 | 16 | asciidoctorj { 17 | def ghTag = snapshotBuild ? 'main' : project.version 18 | def ghUrl = "https://github.com/spring-projects/spring-authorization-server/tree/$ghTag" 19 | attributes 'spring-authorization-server-version' : project.version, 20 | 'spring-boot-version' : springBootVersion, 21 | revnumber : project.version, 22 | 'gh-url': ghUrl, 23 | 'gh-samples-url': "$ghUrl/samples" 24 | attributeProvider resolvedVersions(project.configurations.testCompile) 25 | } 26 | 27 | def resolvedVersions(Configuration configuration) { 28 | return { 29 | configuration.resolvedConfiguration 30 | .resolvedArtifacts 31 | .collectEntries { [(it.name + "-version"): it.moduleVersion.id.version] } 32 | } 33 | } 34 | 35 | repositories { 36 | maven { url "https://repo.spring.io/release" } 37 | } 38 | -------------------------------------------------------------------------------- /gradle/dependency-management.gradle: -------------------------------------------------------------------------------- 1 | if (!project.hasProperty("springVersion")) { 2 | ext.springVersion = "5.3.9" 3 | } 4 | 5 | if (!project.hasProperty("springSecurityVersion")) { 6 | ext.springSecurityVersion = "5.5.2" 7 | } 8 | 9 | if (!project.hasProperty("reactorVersion")) { 10 | ext.reactorVersion = "2020.0.10" 11 | } 12 | 13 | if (!project.hasProperty("locksDisabled")) { 14 | dependencyLocking { 15 | lockAllConfigurations() 16 | } 17 | } 18 | 19 | dependencyManagement { 20 | imports { 21 | mavenBom "org.springframework:spring-framework-bom:$springVersion" 22 | mavenBom "org.springframework.security:spring-security-bom:$springSecurityVersion" 23 | mavenBom "io.projectreactor:reactor-bom:$reactorVersion" 24 | mavenBom "com.fasterxml.jackson:jackson-bom:2.12.4" 25 | } 26 | 27 | dependencies { 28 | dependency "com.nimbusds:nimbus-jose-jwt:9.10.1" 29 | dependency "javax.servlet:javax.servlet-api:4.0.1" 30 | dependency 'junit:junit:4.13.2' 31 | dependency 'org.assertj:assertj-core:3.19.0' 32 | dependency 'org.mockito:mockito-core:3.9.0' 33 | dependency "com.squareup.okhttp3:mockwebserver:3.14.9" 34 | dependency "com.squareup.okhttp3:okhttp:3.14.9" 35 | dependency "com.jayway.jsonpath:json-path:2.5.0" 36 | dependency "org.hsqldb:hsqldb:2.5.2" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/HashSetMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.jackson2; 17 | 18 | import java.util.HashSet; 19 | import java.util.Set; 20 | 21 | import com.fasterxml.jackson.annotation.JsonCreator; 22 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 23 | 24 | /** 25 | * This mixin class is used to serialize/deserialize {@link HashSet}. 26 | * 27 | * @author Steve Riesenberg 28 | * @since 0.1.2 29 | * @see HashSet 30 | */ 31 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 32 | abstract class HashSetMixin { 33 | 34 | @JsonCreator 35 | HashSetMixin(Set set) { 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/Version.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core; 17 | 18 | /** 19 | * Internal class used for serialization across Spring Security Authorization Server classes. 20 | * 21 | * @author Anoop Garlapati 22 | * @since 0.0.1 23 | */ 24 | public final class Version { 25 | private static final int MAJOR = 0; 26 | private static final int MINOR = 2; 27 | private static final int PATCH = 1; 28 | 29 | /** 30 | * Global Serialization value for Spring Security Authorization Server classes. 31 | */ 32 | public static final long SERIAL_VERSION_UID = getVersion().hashCode(); 33 | 34 | public static String getVersion() { 35 | return MAJOR + "." + MINOR + "." + PATCH; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/resources/org/springframework/security/oauth2/server/authorization/custom-oauth2-authorization-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE oauth2Authorization ( 2 | id varchar(100) NOT NULL, 3 | registeredClientId varchar(100) NOT NULL, 4 | principalName varchar(200) NOT NULL, 5 | authorizationGrantType varchar(100) NOT NULL, 6 | attributes varchar(4000) DEFAULT NULL, 7 | state varchar(500) DEFAULT NULL, 8 | authorizationCodeValue varchar(1000) DEFAULT NULL, 9 | authorizationCodeIssuedAt timestamp DEFAULT NULL, 10 | authorizationCodeExpiresAt timestamp DEFAULT NULL, 11 | authorizationCodeMetadata varchar(2000) DEFAULT NULL, 12 | accessTokenValue varchar(1000) DEFAULT NULL, 13 | accessTokenIssuedAt timestamp DEFAULT NULL, 14 | accessTokenExpiresAt timestamp DEFAULT NULL, 15 | accessTokenMetadata varchar(2000) DEFAULT NULL, 16 | accessTokenType varchar(100) DEFAULT NULL, 17 | accessTokenScopes varchar(1000) DEFAULT NULL, 18 | oidcIdTokenValue varchar(1000) DEFAULT NULL, 19 | oidcIdTokenIssuedAt timestamp DEFAULT NULL, 20 | oidcIdTokenExpiresAt timestamp DEFAULT NULL, 21 | oidcIdTokenMetadata varchar(2000) DEFAULT NULL, 22 | refreshTokenValue varchar(1000) DEFAULT NULL, 23 | refreshTokenIssuedAt timestamp DEFAULT NULL, 24 | refreshTokenExpiresAt timestamp DEFAULT NULL, 25 | refreshTokenMetadata varchar(2000) DEFAULT NULL, 26 | PRIMARY KEY (id) 27 | ); 28 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/resources/org/springframework/security/oauth2/server/authorization/oauth2-authorization-schema.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE oauth2_authorization ( 2 | id varchar(100) NOT NULL, 3 | registered_client_id varchar(100) NOT NULL, 4 | principal_name varchar(200) NOT NULL, 5 | authorization_grant_type varchar(100) NOT NULL, 6 | attributes varchar(4000) DEFAULT NULL, 7 | state varchar(500) DEFAULT NULL, 8 | authorization_code_value blob DEFAULT NULL, 9 | authorization_code_issued_at timestamp DEFAULT NULL, 10 | authorization_code_expires_at timestamp DEFAULT NULL, 11 | authorization_code_metadata varchar(2000) DEFAULT NULL, 12 | access_token_value blob DEFAULT NULL, 13 | access_token_issued_at timestamp DEFAULT NULL, 14 | access_token_expires_at timestamp DEFAULT NULL, 15 | access_token_metadata varchar(2000) DEFAULT NULL, 16 | access_token_type varchar(100) DEFAULT NULL, 17 | access_token_scopes varchar(1000) DEFAULT NULL, 18 | oidc_id_token_value blob DEFAULT NULL, 19 | oidc_id_token_issued_at timestamp DEFAULT NULL, 20 | oidc_id_token_expires_at timestamp DEFAULT NULL, 21 | oidc_id_token_metadata varchar(2000) DEFAULT NULL, 22 | refresh_token_value blob DEFAULT NULL, 23 | refresh_token_issued_at timestamp DEFAULT NULL, 24 | refresh_token_expires_at timestamp DEFAULT NULL, 25 | refresh_token_metadata varchar(2000) DEFAULT NULL, 26 | PRIMARY KEY (id) 27 | ); 28 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2TokenCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization; 17 | 18 | /** 19 | * Implementations of this interface are responsible for customizing the 20 | * OAuth 2.0 Token attributes contained within the {@link OAuth2TokenContext}. 21 | * 22 | * @author Joe Grandja 23 | * @since 0.1.0 24 | * @see OAuth2TokenContext 25 | * @param the type of the context containing the OAuth 2.0 Token attributes 26 | */ 27 | @FunctionalInterface 28 | public interface OAuth2TokenCustomizer { 29 | 30 | /** 31 | * Customize the OAuth 2.0 Token attributes. 32 | * 33 | * @param context the context containing the OAuth 2.0 Token attributes 34 | */ 35 | void customize(T context); 36 | 37 | } 38 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/SignatureAlgorithmMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.jackson2; 17 | 18 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 19 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 20 | 21 | import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; 22 | 23 | /** 24 | * This mixin class is used to serialize/deserialize {@link SignatureAlgorithm}. 25 | * 26 | * @author Joe Grandja 27 | * @since 0.1.2 28 | * @see SignatureAlgorithm 29 | */ 30 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 31 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, 32 | isGetterVisibility = JsonAutoDetect.Visibility.NONE) 33 | abstract class SignatureAlgorithmMixin { 34 | } 35 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtEncodingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.jwt; 17 | 18 | /** 19 | * This exception is thrown when an error occurs 20 | * while attempting to encode a JSON Web Token (JWT). 21 | * 22 | * @author Joe Grandja 23 | * @since 0.0.1 24 | */ 25 | public class JwtEncodingException extends JwtException { 26 | 27 | /** 28 | * Constructs a {@code JwtEncodingException} using the provided parameters. 29 | * 30 | * @param message the detail message 31 | */ 32 | public JwtEncodingException(String message) { 33 | super(message); 34 | } 35 | 36 | /** 37 | * Constructs a {@code JwtEncodingException} using the provided parameters. 38 | * 39 | * @param message the detail message 40 | * @param cause the root cause 41 | */ 42 | public JwtEncodingException(String message, Throwable cause) { 43 | super(message, cause); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /samples/messages-resource/src/main/java/sample/config/ResourceServerConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 20 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 21 | import org.springframework.security.web.SecurityFilterChain; 22 | 23 | /** 24 | * @author Joe Grandja 25 | * @since 0.0.1 26 | */ 27 | @EnableWebSecurity 28 | public class ResourceServerConfig { 29 | 30 | // @formatter:off 31 | @Bean 32 | SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { 33 | http 34 | .mvcMatcher("/messages/**") 35 | .authorizeRequests() 36 | .mvcMatchers("/messages/**").access("hasAuthority('SCOPE_message.read')") 37 | .and() 38 | .oauth2ResourceServer() 39 | .jwt(); 40 | return http.build(); 41 | } 42 | // @formatter:on 43 | 44 | } 45 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/TestJwtClaimsSets.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.jwt; 17 | 18 | import java.time.Instant; 19 | import java.time.temporal.ChronoUnit; 20 | import java.util.Collections; 21 | 22 | /** 23 | * @author Joe Grandja 24 | */ 25 | public final class TestJwtClaimsSets { 26 | 27 | private TestJwtClaimsSets() { 28 | } 29 | 30 | public static JwtClaimsSet.Builder jwtClaimsSet() { 31 | String issuer = "https://provider.com"; 32 | Instant issuedAt = Instant.now(); 33 | Instant expiresAt = issuedAt.plus(1, ChronoUnit.HOURS); 34 | 35 | // @formatter:off 36 | return JwtClaimsSet.builder() 37 | .issuer(issuer) 38 | .subject("subject") 39 | .audience(Collections.singletonList("client-1")) 40 | .issuedAt(issuedAt) 41 | .notBefore(issuedAt) 42 | .expiresAt(expiresAt) 43 | .id("jti") 44 | .claim("custom-claim-name", "custom-claim-value"); 45 | // @formatter:on 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core; 17 | 18 | import java.time.Instant; 19 | 20 | /** 21 | * An implementation of an {@link AbstractOAuth2Token} 22 | * representing an OAuth 2.0 Authorization Code Grant. 23 | * 24 | * @author Joe Grandja 25 | * @since 0.0.3 26 | * @see AbstractOAuth2Token 27 | * @see Section 4.1 Authorization Code Grant 28 | */ 29 | public class OAuth2AuthorizationCode extends AbstractOAuth2Token { 30 | 31 | /** 32 | * Constructs an {@code OAuth2AuthorizationCode} using the provided parameters. 33 | * @param tokenValue the token value 34 | * @param issuedAt the time at which the token was issued 35 | * @param expiresAt the time at which the token expires 36 | */ 37 | public OAuth2AuthorizationCode(String tokenValue, Instant issuedAt, Instant expiresAt) { 38 | super(tokenValue, issuedAt, expiresAt); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/config/test/SpringTestRule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2017 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.config.test; 18 | 19 | import org.junit.rules.MethodRule; 20 | import org.junit.runners.model.FrameworkMethod; 21 | import org.junit.runners.model.Statement; 22 | import org.springframework.security.test.context.TestSecurityContextHolder; 23 | 24 | /** 25 | * TODO 26 | * This class is a straight copy from Spring Security. 27 | * It should be removed when merging this codebase into Spring Security. 28 | * 29 | * @author Rob Winch 30 | * @since 5.0 31 | */ 32 | public class SpringTestRule extends SpringTestContext implements MethodRule { 33 | @Override 34 | public Statement apply(Statement base, FrameworkMethod method, Object target) { 35 | return new Statement() { 36 | public void evaluate() throws Throwable { 37 | setTest(target); 38 | try { 39 | base.evaluate(); 40 | } finally { 41 | TestSecurityContextHolder.clearContext(); 42 | close(); 43 | } 44 | } 45 | }; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8080 3 | 4 | logging: 5 | level: 6 | root: INFO 7 | org.springframework.web: INFO 8 | org.springframework.security: INFO 9 | org.springframework.security.oauth2: INFO 10 | # org.springframework.boot.autoconfigure: DEBUG 11 | 12 | spring: 13 | thymeleaf: 14 | cache: false 15 | security: 16 | oauth2: 17 | client: 18 | registration: 19 | messaging-client-oidc: 20 | provider: spring 21 | client-id: messaging-client 22 | client-secret: secret 23 | authorization-grant-type: authorization_code 24 | redirect-uri: "http://127.0.0.1:8080/login/oauth2/code/{registrationId}" 25 | scope: openid 26 | client-name: messaging-client-oidc 27 | messaging-client-authorization-code: 28 | provider: spring 29 | client-id: messaging-client 30 | client-secret: secret 31 | authorization-grant-type: authorization_code 32 | redirect-uri: "http://127.0.0.1:8080/authorized" 33 | scope: message.read,message.write 34 | client-name: messaging-client-authorization-code 35 | messaging-client-client-credentials: 36 | provider: spring 37 | client-id: messaging-client 38 | client-secret: secret 39 | authorization-grant-type: client_credentials 40 | scope: message.read,message.write 41 | client-name: messaging-client-client-credentials 42 | provider: 43 | spring: 44 | issuer-uri: http://auth-server:9000 45 | 46 | messages: 47 | base-uri: http://127.0.0.1:8090/messages 48 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/authentication/OAuth2AuthenticationValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.authentication; 17 | 18 | import org.springframework.security.core.Authentication; 19 | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; 20 | 21 | /** 22 | * Implementations of this interface are responsible for validating the attribute(s) 23 | * of the {@link Authentication} associated to the {@link OAuth2AuthenticationContext}. 24 | * 25 | * @author Joe Grandja 26 | * @since 0.2.0 27 | * @see OAuth2AuthenticationContext 28 | */ 29 | @FunctionalInterface 30 | public interface OAuth2AuthenticationValidator { 31 | 32 | /** 33 | * Validate the attribute(s) of the {@link Authentication}. 34 | * 35 | * @param authenticationContext the authentication context 36 | * @throws OAuth2AuthenticationException if the attribute(s) of the {@code Authentication} is invalid 37 | */ 38 | void validate(OAuth2AuthenticationContext authenticationContext) throws OAuth2AuthenticationException; 39 | 40 | } 41 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2EndpointUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.web; 17 | 18 | import java.util.Map; 19 | 20 | import javax.servlet.http.HttpServletRequest; 21 | 22 | import org.springframework.util.LinkedMultiValueMap; 23 | import org.springframework.util.MultiValueMap; 24 | 25 | /** 26 | * Utility methods for the OAuth 2.0 Protocol Endpoints. 27 | * 28 | * @author Joe Grandja 29 | * @since 0.0.1 30 | */ 31 | final class OAuth2EndpointUtils { 32 | 33 | private OAuth2EndpointUtils() { 34 | } 35 | 36 | static MultiValueMap getParameters(HttpServletRequest request) { 37 | Map parameterMap = request.getParameterMap(); 38 | MultiValueMap parameters = new LinkedMultiValueMap<>(parameterMap.size()); 39 | parameterMap.forEach((key, values) -> { 40 | if (values.length > 0) { 41 | for (String value : values) { 42 | parameters.add(key, value); 43 | } 44 | } 45 | }); 46 | return parameters; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /SUPPORT_POLICY.adoc: -------------------------------------------------------------------------------- 1 | = Spring Authorization Server Support Policy 2 | 3 | The Spring Authorization Server support offering provides the following support terms: 4 | 5 | * Releases are currently in the format of 0.x.y, where: 6 | ** “x” contains new features and potentially breaking changes. 7 | ** “y” contains new features and bug fixes and provides backward compatibility. 8 | * The Spring Authorization Server project will be supported for at least 3 years after the most recent 0.x.0 release is made available for download. 9 | * Security fixes will be provided for at least one year after the 0.x.0 release is made available for download. Security fixes will not be provided for updating versions to third-party libraries. 10 | * Feature support and bug fixes, excluding “Security fixes”, will be provided only for the latest 0.x.y release. 11 | * This support policy starts with version 0.2.0. 12 | * We will switch to the standard https://tanzu.vmware.com/support/oss[Spring OSS support policy] when the Spring Authorization Server project reaches version 1.0.0. 13 | 14 | An example can help us understand all of these points. 15 | Assume that 0.2.0 is released in August of 2021. 16 | This means that the Spring Authorization Server project is supported until at least August of 2024. 17 | If 0.3.0 is then released in May of 2022, the Spring Authorization Server project is supported until at least May of 2025. 18 | The 0.3.0 release may contain breaking changes from 0.2.0. 19 | If a bug is found, only 0.3.0 will be patched in a 0.3.1 release. 20 | If a security vulnerability is found, a 0.2.4 (assume 0.2.3 is latest) and 0.3.1 release will be provided to fix the security vulnerability. 21 | However, a vulnerability found in September of 2022 would be fixed in the 0.3.1 release but not the 0.2.3 release, because the vulnerability was discovered more than a year after the 0.2.0 release date. 22 | -------------------------------------------------------------------------------- /etc/checkstyle/checkstyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/UnmodifiableMapMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.oauth2.server.authorization.jackson2; 18 | 19 | import java.util.Collections; 20 | import java.util.Map; 21 | 22 | import com.fasterxml.jackson.annotation.JsonCreator; 23 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 24 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 25 | 26 | /** 27 | * TODO 28 | * This class is a straight copy from Spring Security. 29 | * It should be consolidated when merging this codebase into Spring Security. 30 | * 31 | * This mixin class is used to serialize/deserialize 32 | * {@link Collections#unmodifiableMap(Map)}. It also registers a custom deserializer 33 | * {@link UnmodifiableMapDeserializer}. 34 | * 35 | * @author Joe Grandja 36 | * @since 5.3 37 | * @see Collections#unmodifiableMap(Map) 38 | * @see UnmodifiableMapDeserializer 39 | */ 40 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 41 | @JsonDeserialize(using = UnmodifiableMapDeserializer.class) 42 | abstract class UnmodifiableMapMixin { 43 | 44 | @JsonCreator 45 | UnmodifiableMapMixin(Map map) { 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/config/annotation/web/configuration/OAuth2AuthorizationServerConfigurationTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.config.annotation.web.configuration; 17 | 18 | import org.junit.Test; 19 | import org.springframework.core.Ordered; 20 | import org.springframework.core.annotation.OrderUtils; 21 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 22 | import org.springframework.util.ClassUtils; 23 | 24 | import java.lang.reflect.Method; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * Tests for {@link OAuth2AuthorizationServerConfiguration}. 30 | * 31 | * @author Joe Grandja 32 | */ 33 | public class OAuth2AuthorizationServerConfigurationTests { 34 | 35 | @Test 36 | public void assertOrderHighestPrecedence() { 37 | Method authorizationServerSecurityFilterChainMethod = 38 | ClassUtils.getMethod( 39 | OAuth2AuthorizationServerConfiguration.class, 40 | "authorizationServerSecurityFilterChain", 41 | HttpSecurity.class); 42 | Integer order = OrderUtils.getOrder(authorizationServerSecurityFilterChainMethod); 43 | assertThat(order).isEqualTo(Ordered.HIGHEST_PRECEDENCE); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/java/sample/config/SecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 20 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 21 | import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer; 22 | import org.springframework.security.web.SecurityFilterChain; 23 | 24 | import static org.springframework.security.config.Customizer.withDefaults; 25 | 26 | /** 27 | * @author Joe Grandja 28 | * @since 0.0.1 29 | */ 30 | @EnableWebSecurity 31 | public class SecurityConfig { 32 | 33 | @Bean 34 | WebSecurityCustomizer webSecurityCustomizer() { 35 | return (web) -> web.ignoring().antMatchers("/webjars/**"); 36 | } 37 | 38 | // @formatter:off 39 | @Bean 40 | SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { 41 | http 42 | .authorizeRequests(authorizeRequests -> 43 | authorizeRequests.anyRequest().authenticated() 44 | ) 45 | .oauth2Login(oauth2Login -> 46 | oauth2Login.loginPage("/oauth2/authorization/messaging-client-oidc")) 47 | .oauth2Client(withDefaults()); 48 | return http.build(); 49 | } 50 | // @formatter:on 51 | 52 | } 53 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcProviderMetadataClaimNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.oidc; 17 | 18 | import org.springframework.security.oauth2.core.OAuth2AuthorizationServerMetadataClaimNames; 19 | import org.springframework.security.oauth2.jose.jws.JwsAlgorithm; 20 | 21 | /** 22 | * The names of the "claims" defined by OpenID Connect Discovery 1.0 that can be returned 23 | * in the OpenID Provider Configuration Response. 24 | * 25 | * @author Daniel Garnier-Moiroux 26 | * @since 0.1.0 27 | * @see OAuth2AuthorizationServerMetadataClaimNames 28 | * @see 3. OpenID Provider Metadata 29 | */ 30 | public interface OidcProviderMetadataClaimNames extends OAuth2AuthorizationServerMetadataClaimNames { 31 | 32 | /** 33 | * {@code subject_types_supported} - the Subject Identifier types supported 34 | */ 35 | String SUBJECT_TYPES_SUPPORTED = "subject_types_supported"; 36 | 37 | /** 38 | * {@code id_token_signing_alg_values_supported} - the {@link JwsAlgorithm JWS} signing algorithms supported for the {@link OidcIdToken ID Token} 39 | */ 40 | String ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED = "id_token_signing_alg_values_supported"; 41 | 42 | } 43 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/DurationMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.jackson2; 17 | 18 | import java.time.Duration; 19 | 20 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 21 | import com.fasterxml.jackson.annotation.JsonCreator; 22 | import com.fasterxml.jackson.annotation.JsonGetter; 23 | import com.fasterxml.jackson.annotation.JsonProperty; 24 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 25 | 26 | /** 27 | * This mixin class is used to serialize/deserialize {@link Duration}. 28 | * 29 | * @author Joe Grandja 30 | * @since 0.1.2 31 | * @see Duration 32 | */ 33 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 34 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.NONE, getterVisibility = JsonAutoDetect.Visibility.NONE, 35 | isGetterVisibility = JsonAutoDetect.Visibility.NONE, setterVisibility = JsonAutoDetect.Visibility.NONE, 36 | creatorVisibility = JsonAutoDetect.Visibility.NONE) 37 | abstract class DurationMixin { 38 | 39 | @JsonCreator 40 | static void ofSeconds(@JsonProperty("seconds") long seconds, @JsonProperty("nano") long nanoAdjustment) { 41 | } 42 | 43 | @JsonGetter("seconds") 44 | abstract long getSeconds(); 45 | 46 | @JsonGetter("nano") 47 | abstract int getNano(); 48 | 49 | } 50 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/server/authorization/AbstractOAuth2Configurer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization; 17 | 18 | import org.springframework.security.config.annotation.ObjectPostProcessor; 19 | import org.springframework.security.config.annotation.web.HttpSecurityBuilder; 20 | import org.springframework.security.web.util.matcher.RequestMatcher; 21 | 22 | /** 23 | * Base configurer for an OAuth 2.0 component (e.g. protocol endpoint). 24 | * 25 | * @author Joe Grandja 26 | * @since 0.1.2 27 | */ 28 | abstract class AbstractOAuth2Configurer { 29 | private final ObjectPostProcessor objectPostProcessor; 30 | 31 | AbstractOAuth2Configurer(ObjectPostProcessor objectPostProcessor) { 32 | this.objectPostProcessor = objectPostProcessor; 33 | } 34 | 35 | abstract > void init(B builder); 36 | 37 | abstract > void configure(B builder); 38 | 39 | abstract RequestMatcher getRequestMatcher(); 40 | 41 | protected final T postProcess(T object) { 42 | return (T) this.objectPostProcessor.postProcess(object); 43 | } 44 | 45 | protected final ObjectPostProcessor getObjectPostProcessor() { 46 | return this.objectPostProcessor; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/client/RegisteredClientRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.client; 17 | 18 | import org.springframework.lang.Nullable; 19 | 20 | /** 21 | * A repository for OAuth 2.0 {@link RegisteredClient}(s). 22 | * 23 | * @author Joe Grandja 24 | * @author Anoop Garlapati 25 | * @author Ovidiu Popa 26 | * @see RegisteredClient 27 | * @since 0.0.1 28 | */ 29 | public interface RegisteredClientRepository { 30 | 31 | /** 32 | * Saves the registered client. 33 | * 34 | * @param registeredClient the {@link RegisteredClient} 35 | */ 36 | void save(RegisteredClient registeredClient); 37 | 38 | /** 39 | * Returns the registered client identified by the provided {@code id}, 40 | * or {@code null} if not found. 41 | * 42 | * @param id the registration identifier 43 | * @return the {@link RegisteredClient} if found, otherwise {@code null} 44 | */ 45 | @Nullable 46 | RegisteredClient findById(String id); 47 | 48 | /** 49 | * Returns the registered client identified by the provided {@code clientId}, 50 | * or {@code null} if not found. 51 | * 52 | * @param clientId the client identifier 53 | * @return the {@link RegisteredClient} if found, otherwise {@code null} 54 | */ 55 | @Nullable 56 | RegisteredClient findByClientId(String clientId); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jwt/TestJoseHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.jwt; 17 | 18 | import java.util.Arrays; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; 23 | 24 | /** 25 | * @author Joe Grandja 26 | */ 27 | public final class TestJoseHeaders { 28 | 29 | private TestJoseHeaders() { 30 | } 31 | 32 | public static JoseHeader.Builder joseHeader() { 33 | return joseHeader(SignatureAlgorithm.RS256); 34 | } 35 | 36 | public static JoseHeader.Builder joseHeader(SignatureAlgorithm signatureAlgorithm) { 37 | // @formatter:off 38 | return JoseHeader.withAlgorithm(signatureAlgorithm) 39 | .jwkSetUrl("https://provider.com/oauth2/jwks") 40 | .jwk(rsaJwk()) 41 | .keyId("keyId") 42 | .x509Url("https://provider.com/oauth2/x509") 43 | .x509CertificateChain(Arrays.asList("x509Cert1", "x509Cert2")) 44 | .x509SHA1Thumbprint("x509SHA1Thumbprint") 45 | .x509SHA256Thumbprint("x509SHA256Thumbprint") 46 | .type("JWT") 47 | .contentType("jwt-content-type") 48 | .header("custom-header-name", "custom-header-value"); 49 | // @formatter:on 50 | } 51 | 52 | private static Map rsaJwk() { 53 | Map rsaJwk = new HashMap<>(); 54 | rsaJwk.put("kty", "RSA"); 55 | rsaJwk.put("n", "modulus"); 56 | rsaJwk.put("e", "exponent"); 57 | return rsaJwk; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationRequestMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.oauth2.server.authorization.jackson2; 18 | 19 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 20 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 21 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 22 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 23 | 24 | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; 25 | 26 | /** 27 | * TODO 28 | * This class is a straight copy from Spring Security. 29 | * It should be consolidated when merging this codebase into Spring Security. 30 | * 31 | * This mixin class is used to serialize/deserialize {@link OAuth2AuthorizationRequest}. 32 | * It also registers a custom deserializer {@link OAuth2AuthorizationRequestDeserializer}. 33 | * 34 | * @author Joe Grandja 35 | * @since 5.3 36 | * @see OAuth2AuthorizationRequest 37 | * @see OAuth2AuthorizationRequestDeserializer 38 | */ 39 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 40 | @JsonDeserialize(using = OAuth2AuthorizationRequestDeserializer.class) 41 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, 42 | isGetterVisibility = JsonAutoDetect.Visibility.NONE) 43 | @JsonIgnoreProperties(ignoreUnknown = true) 44 | abstract class OAuth2AuthorizationRequestMixin { 45 | 46 | } 47 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson2/TestingAuthenticationTokenMixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.jackson2; 17 | 18 | import java.util.List; 19 | 20 | import com.fasterxml.jackson.annotation.JsonAutoDetect; 21 | import com.fasterxml.jackson.annotation.JsonCreator; 22 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 23 | import com.fasterxml.jackson.annotation.JsonProperty; 24 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 25 | 26 | import org.springframework.security.authentication.TestingAuthenticationToken; 27 | import org.springframework.security.core.GrantedAuthority; 28 | 29 | /** 30 | * This mixin class is used to serialize/deserialize {@link TestingAuthenticationToken}. 31 | * 32 | * @author Steve Riesenberg 33 | * @since 0.1.2 34 | * @see TestingAuthenticationToken 35 | */ 36 | @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) 37 | @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE, 38 | isGetterVisibility = JsonAutoDetect.Visibility.NONE) 39 | @JsonIgnoreProperties(value = { "authenticated" }, ignoreUnknown = true) 40 | public class TestingAuthenticationTokenMixin { 41 | 42 | @JsonCreator 43 | TestingAuthenticationTokenMixin(@JsonProperty("principal") Object principal, 44 | @JsonProperty("credentials") Object credentials, 45 | @JsonProperty("authorities") List authorities) { 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /samples/custom-consent-authorizationserver/src/main/java/sample/config/DefaultSecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 20 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 21 | import org.springframework.security.core.userdetails.User; 22 | import org.springframework.security.core.userdetails.UserDetails; 23 | import org.springframework.security.core.userdetails.UserDetailsService; 24 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 25 | import org.springframework.security.web.SecurityFilterChain; 26 | 27 | import static org.springframework.security.config.Customizer.withDefaults; 28 | 29 | /** 30 | * @author Joe Grandja 31 | */ 32 | @EnableWebSecurity 33 | public class DefaultSecurityConfig { 34 | 35 | // @formatter:off 36 | @Bean 37 | SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { 38 | http 39 | .authorizeRequests(authorizeRequests -> 40 | authorizeRequests.anyRequest().authenticated() 41 | ) 42 | .formLogin(withDefaults()); 43 | return http.build(); 44 | } 45 | // @formatter:on 46 | 47 | // @formatter:off 48 | @Bean 49 | UserDetailsService users() { 50 | UserDetails user = User.withDefaultPasswordEncoder() 51 | .username("user1") 52 | .password("password") 53 | .roles("USER") 54 | .build(); 55 | return new InMemoryUserDetailsManager(user); 56 | } 57 | // @formatter:on 58 | 59 | } 60 | -------------------------------------------------------------------------------- /samples/default-authorizationserver/src/main/java/sample/config/DefaultSecurityConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 20 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 21 | import org.springframework.security.core.userdetails.User; 22 | import org.springframework.security.core.userdetails.UserDetails; 23 | import org.springframework.security.core.userdetails.UserDetailsService; 24 | import org.springframework.security.provisioning.InMemoryUserDetailsManager; 25 | import org.springframework.security.web.SecurityFilterChain; 26 | 27 | import static org.springframework.security.config.Customizer.withDefaults; 28 | 29 | /** 30 | * @author Joe Grandja 31 | * @since 0.1.0 32 | */ 33 | @EnableWebSecurity 34 | public class DefaultSecurityConfig { 35 | 36 | // @formatter:off 37 | @Bean 38 | SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { 39 | http 40 | .authorizeRequests(authorizeRequests -> 41 | authorizeRequests.anyRequest().authenticated() 42 | ) 43 | .formLogin(withDefaults()); 44 | return http.build(); 45 | } 46 | // @formatter:on 47 | 48 | // @formatter:off 49 | @Bean 50 | UserDetailsService users() { 51 | UserDetails user = User.withDefaultPasswordEncoder() 52 | .username("user1") 53 | .password("password") 54 | .roles("USER") 55 | .build(); 56 | return new InMemoryUserDetailsManager(user); 57 | } 58 | // @formatter:on 59 | 60 | } 61 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/context/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.context; 17 | 18 | import org.springframework.lang.Nullable; 19 | import org.springframework.util.Assert; 20 | 21 | /** 22 | * A facility for holding information associated to a specific context. 23 | * 24 | * @author Joe Grandja 25 | * @since 0.1.0 26 | */ 27 | public interface Context { 28 | 29 | /** 30 | * Returns the value of the attribute associated to the key. 31 | * 32 | * @param key the key for the attribute 33 | * @param the type of the value for the attribute 34 | * @return the value of the attribute associated to the key, or {@code null} if not available 35 | */ 36 | @Nullable 37 | V get(Object key); 38 | 39 | /** 40 | * Returns the value of the attribute associated to the key. 41 | * 42 | * @param key the key for the attribute 43 | * @param the type of the value for the attribute 44 | * @return the value of the attribute associated to the key, or {@code null} if not available or not of the specified type 45 | */ 46 | @Nullable 47 | default V get(Class key) { 48 | Assert.notNull(key, "key cannot be null"); 49 | V value = get((Object) key); 50 | return key.isInstance(value) ? value : null; 51 | } 52 | 53 | /** 54 | * Returns {@code true} if an attribute associated to the key exists, {@code false} otherwise. 55 | * 56 | * @param key the key for the attribute 57 | * @return {@code true} if an attribute associated to the key exists, {@code false} otherwise 58 | */ 59 | boolean hasKey(Object key); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationConsentService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization; 17 | 18 | import org.springframework.lang.Nullable; 19 | import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; 20 | 21 | import java.security.Principal; 22 | 23 | /** 24 | * Implementations of this interface are responsible for the management 25 | * of {@link OAuth2AuthorizationConsent OAuth 2.0 Authorization Consent(s)}. 26 | * 27 | * @author Daniel Garnier-Moiroux 28 | * @since 0.1.2 29 | * @see OAuth2AuthorizationConsent 30 | */ 31 | public interface OAuth2AuthorizationConsentService { 32 | 33 | /** 34 | * Saves the {@link OAuth2AuthorizationConsent}. 35 | * 36 | * @param authorizationConsent the {@link OAuth2AuthorizationConsent} 37 | */ 38 | void save(OAuth2AuthorizationConsent authorizationConsent); 39 | 40 | /** 41 | * Removes the {@link OAuth2AuthorizationConsent}. 42 | * 43 | * @param authorizationConsent the {@link OAuth2AuthorizationConsent} 44 | */ 45 | void remove(OAuth2AuthorizationConsent authorizationConsent); 46 | 47 | /** 48 | * Returns the {@link OAuth2AuthorizationConsent} identified by the provided 49 | * {@code registeredClientId} and {@code principalName}, or {@code null} if not found. 50 | * 51 | * @param registeredClientId the identifier for the {@link RegisteredClient} 52 | * @param principalName the name of the {@link Principal} 53 | * @return the {@link OAuth2AuthorizationConsent} if found, otherwise {@code null} 54 | */ 55 | @Nullable 56 | OAuth2AuthorizationConsent findById(String registeredClientId, String principalName); 57 | 58 | } 59 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core; 17 | 18 | import java.io.Serializable; 19 | 20 | import org.springframework.util.Assert; 21 | 22 | /** 23 | * Standard token types defined in the OAuth Token Type Hints Registry. 24 | * 25 | * @author Joe Grandja 26 | * @since 0.0.1 27 | * @see 4.1.2 OAuth Token Type Hints Registry 28 | */ 29 | public final class OAuth2TokenType implements Serializable { 30 | private static final long serialVersionUID = Version.SERIAL_VERSION_UID; 31 | public static final OAuth2TokenType ACCESS_TOKEN = new OAuth2TokenType("access_token"); 32 | public static final OAuth2TokenType REFRESH_TOKEN = new OAuth2TokenType("refresh_token"); 33 | private final String value; 34 | 35 | /** 36 | * Constructs an {@code OAuth2TokenType} using the provided value. 37 | * 38 | * @param value the value of the token type 39 | */ 40 | public OAuth2TokenType(String value) { 41 | Assert.hasText(value, "value cannot be empty"); 42 | this.value = value; 43 | } 44 | 45 | /** 46 | * Returns the value of the token type. 47 | * 48 | * @return the value of the token type 49 | */ 50 | public String getValue() { 51 | return this.value; 52 | } 53 | 54 | @Override 55 | public boolean equals(Object obj) { 56 | if (this == obj) { 57 | return true; 58 | } 59 | if (obj == null || this.getClass() != obj.getClass()) { 60 | return false; 61 | } 62 | OAuth2TokenType that = (OAuth2TokenType) obj; 63 | return getValue().equals(that.getValue()); 64 | } 65 | 66 | @Override 67 | public int hashCode() { 68 | return getValue().hashCode(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/UnmodifiableMapDeserializer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.oauth2.server.authorization.jackson2; 18 | 19 | import java.io.IOException; 20 | import java.util.Collections; 21 | import java.util.LinkedHashMap; 22 | import java.util.Map; 23 | 24 | import com.fasterxml.jackson.core.JsonParser; 25 | import com.fasterxml.jackson.databind.DeserializationContext; 26 | import com.fasterxml.jackson.databind.JsonDeserializer; 27 | import com.fasterxml.jackson.databind.JsonNode; 28 | import com.fasterxml.jackson.databind.ObjectMapper; 29 | 30 | /** 31 | * TODO 32 | * This class is a straight copy from Spring Security. 33 | * It should be consolidated when merging this codebase into Spring Security. 34 | * 35 | * A {@code JsonDeserializer} for {@link Collections#unmodifiableMap(Map)}. 36 | * 37 | * @author Joe Grandja 38 | * @since 5.3 39 | * @see Collections#unmodifiableMap(Map) 40 | * @see UnmodifiableMapMixin 41 | */ 42 | final class UnmodifiableMapDeserializer extends JsonDeserializer> { 43 | 44 | @Override 45 | public Map deserialize(JsonParser parser, DeserializationContext context) throws IOException { 46 | ObjectMapper mapper = (ObjectMapper) parser.getCodec(); 47 | JsonNode mapNode = mapper.readTree(parser); 48 | Map result = new LinkedHashMap<>(); 49 | if (mapNode != null && mapNode.isObject()) { 50 | Iterable> fields = mapNode::fields; 51 | for (Map.Entry field : fields) { 52 | result.put(field.getKey(), mapper.readValue(field.getValue().traverse(mapper), Object.class)); 53 | } 54 | } 55 | return Collections.unmodifiableMap(result); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /.github/workflows/continuous-integration-workflow.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | schedule: 8 | - cron: '0 10 * * *' # Once per day at 10am UTC 9 | 10 | jobs: 11 | build: 12 | name: Build 13 | runs-on: ${{ matrix.os }} 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest, macos-latest, windows-latest] 17 | jdk: [8,11,12] 18 | fail-fast: false 19 | steps: 20 | - uses: actions/checkout@v2 21 | - name: Set up JDK ${{ matrix.jdk }} 22 | uses: actions/setup-java@v1 23 | with: 24 | java-version: ${{ matrix.jdk }} 25 | - name: Build with Gradle 26 | run: ./gradlew clean build 27 | snapshot_tests: 28 | name: Test against snapshots 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v2 32 | - name: Set up JDK 33 | uses: actions/setup-java@v1 34 | with: 35 | java-version: 8 36 | - name: Test 37 | run: echo Testing against snapshots 38 | sonar: 39 | name: Static Code Analysis 40 | runs-on: ubuntu-latest 41 | steps: 42 | - uses: actions/checkout@v2 43 | - name: Set up JDK 44 | uses: actions/setup-java@v1 45 | with: 46 | java-version: 8 47 | - name: Sonar 48 | run: echo Running Sonarqube static code analysis 49 | artifacts: 50 | name: Deploy Artifacts 51 | needs: [build, snapshot_tests, sonar] 52 | runs-on: ubuntu-latest 53 | steps: 54 | - uses: actions/checkout@v2 55 | - name: Set up JDK 56 | uses: actions/setup-java@v1 57 | with: 58 | java-version: 8 59 | - name: Deploy Artifacts 60 | run: echo Deploying Artifacts 61 | docs: 62 | name: Deploy Docs 63 | needs: [build, snapshot_tests, sonar] 64 | runs-on: ubuntu-latest 65 | steps: 66 | - uses: actions/checkout@v2 67 | - name: Set up JDK 68 | uses: actions/setup-java@v1 69 | with: 70 | java-version: 8 71 | - name: Deploy Docs 72 | run: echo Deploying Docs 73 | schema: 74 | name: Deploy Schema 75 | needs: [build, snapshot_tests, sonar] 76 | runs-on: ubuntu-latest 77 | steps: 78 | - uses: actions/checkout@v2 79 | - name: Set up JDK 80 | uses: actions/setup-java@v1 81 | with: 82 | java-version: 8 83 | - name: Deploy Schema 84 | run: echo Deploying Schema 85 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/config/ClientSettingsTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.config; 17 | 18 | import org.junit.Test; 19 | 20 | import static org.assertj.core.api.Assertions.assertThat; 21 | 22 | /** 23 | * Tests for {@link ClientSettings}. 24 | * 25 | * @author Joe Grandja 26 | */ 27 | public class ClientSettingsTests { 28 | 29 | @Test 30 | public void buildWhenDefaultThenDefaultsAreSet() { 31 | ClientSettings clientSettings = ClientSettings.builder().build(); 32 | assertThat(clientSettings.getSettings()).hasSize(2); 33 | assertThat(clientSettings.isRequireProofKey()).isFalse(); 34 | assertThat(clientSettings.isRequireAuthorizationConsent()).isFalse(); 35 | } 36 | 37 | @Test 38 | public void requireProofKeyWhenTrueThenSet() { 39 | ClientSettings clientSettings = ClientSettings.builder() 40 | .requireProofKey(true) 41 | .build(); 42 | assertThat(clientSettings.isRequireProofKey()).isTrue(); 43 | } 44 | 45 | @Test 46 | public void requireAuthorizationConsentWhenTrueThenSet() { 47 | ClientSettings clientSettings = ClientSettings.builder() 48 | .requireAuthorizationConsent(true) 49 | .build(); 50 | assertThat(clientSettings.isRequireAuthorizationConsent()).isTrue(); 51 | } 52 | 53 | @Test 54 | public void settingWhenCustomThenSet() { 55 | ClientSettings clientSettings = ClientSettings.builder() 56 | .setting("name1", "value1") 57 | .settings(settings -> settings.put("name2", "value2")) 58 | .build(); 59 | assertThat(clientSettings.getSettings()).hasSize(4); 60 | assertThat(clientSettings.getSetting("name1")).isEqualTo("value1"); 61 | assertThat(clientSettings.getSetting("name2")).isEqualTo("value2"); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/jwt/JwtEncoder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.jwt; 17 | 18 | /** 19 | * Implementations of this interface are responsible for encoding 20 | * a JSON Web Token (JWT) to it's compact claims representation format. 21 | * 22 | *

23 | * JWTs may be represented using the JWS Compact Serialization format for a 24 | * JSON Web Signature (JWS) structure or JWE Compact Serialization format for a 25 | * JSON Web Encryption (JWE) structure. Therefore, implementors are responsible 26 | * for signing a JWS and/or encrypting a JWE. 27 | * 28 | * @author Anoop Garlapati 29 | * @author Joe Grandja 30 | * @since 0.0.1 31 | * @see Jwt 32 | * @see JoseHeader 33 | * @see JwtClaimsSet 34 | * @see JwtDecoder 35 | * @see JSON Web Token (JWT) 36 | * @see JSON Web Signature (JWS) 37 | * @see JSON Web Encryption (JWE) 38 | * @see JWS Compact Serialization 39 | * @see JWE Compact Serialization 40 | */ 41 | @FunctionalInterface 42 | public interface JwtEncoder { 43 | 44 | /** 45 | * Encode the JWT to it's compact claims representation format. 46 | * 47 | * @param headers the JOSE header 48 | * @param claims the JWT Claims Set 49 | * @return a {@link Jwt} 50 | * @throws JwtEncodingException if an error occurs while attempting to encode the JWT 51 | */ 52 | Jwt encode(JoseHeader headers, JwtClaimsSet claims) throws JwtEncodingException; 53 | 54 | } 55 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/OAuth2AuthorizationService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization; 17 | 18 | import org.springframework.lang.Nullable; 19 | import org.springframework.security.oauth2.core.OAuth2TokenType; 20 | 21 | /** 22 | * Implementations of this interface are responsible for the management 23 | * of {@link OAuth2Authorization OAuth 2.0 Authorization(s)}. 24 | * 25 | * @author Joe Grandja 26 | * @since 0.0.1 27 | * @see OAuth2Authorization 28 | * @see OAuth2TokenType 29 | */ 30 | public interface OAuth2AuthorizationService { 31 | 32 | /** 33 | * Saves the {@link OAuth2Authorization}. 34 | * 35 | * @param authorization the {@link OAuth2Authorization} 36 | */ 37 | void save(OAuth2Authorization authorization); 38 | 39 | /** 40 | * Removes the {@link OAuth2Authorization}. 41 | * 42 | * @param authorization the {@link OAuth2Authorization} 43 | */ 44 | void remove(OAuth2Authorization authorization); 45 | 46 | /** 47 | * Returns the {@link OAuth2Authorization} identified by the provided {@code id}, 48 | * or {@code null} if not found. 49 | * 50 | * @param id the authorization identifier 51 | * @return the {@link OAuth2Authorization} if found, otherwise {@code null} 52 | */ 53 | @Nullable 54 | OAuth2Authorization findById(String id); 55 | 56 | /** 57 | * Returns the {@link OAuth2Authorization} containing the provided {@code token}, 58 | * or {@code null} if not found. 59 | * 60 | * @param token the token credential 61 | * @param tokenType the {@link OAuth2TokenType token type} 62 | * @return the {@link OAuth2Authorization} if found, otherwise {@code null} 63 | */ 64 | @Nullable 65 | OAuth2Authorization findByToken(String token, @Nullable OAuth2TokenType tokenType); 66 | 67 | } 68 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.adoc: -------------------------------------------------------------------------------- 1 | = Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of fostering an open 4 | and welcoming community, we pledge to respect all people who contribute through reporting 5 | issues, posting feature requests, updating documentation, submitting pull requests or 6 | patches, and other activities. 7 | 8 | We are committed to making participation in this project a harassment-free experience for 9 | everyone, regardless of level of experience, gender, gender identity and expression, 10 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, 11 | religion, or nationality. 12 | 13 | Examples of unacceptable behavior by participants include: 14 | 15 | * The use of sexualized language or imagery 16 | * Personal attacks 17 | * Trolling or insulting/derogatory comments 18 | * Public or private harassment 19 | * Publishing other's private information, such as physical or electronic addresses, 20 | without explicit permission 21 | * Other unethical or unprofessional conduct 22 | 23 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 24 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 25 | Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors 26 | that they deem inappropriate, threatening, offensive, or harmful. 27 | 28 | By adopting this Code of Conduct, project maintainers commit themselves to fairly and 29 | consistently applying these principles to every aspect of managing this project. Project 30 | maintainers who do not follow or enforce the Code of Conduct may be permanently removed 31 | from the project team. 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an 34 | individual is representing the project or its community. 35 | 36 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 37 | contacting a project maintainer at spring-code-of-conduct@pivotal.io . All complaints will 38 | be reviewed and investigated and will result in a response that is deemed necessary and 39 | appropriate to the circumstances. Maintainers are obligated to maintain confidentiality 40 | with regard to the reporter of an incident. 41 | 42 | This Code of Conduct is adapted from the 43 | https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at 44 | https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/] 45 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/JsonNodeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.oauth2.server.authorization.jackson2; 18 | 19 | import java.util.Map; 20 | import java.util.Set; 21 | 22 | import com.fasterxml.jackson.core.type.TypeReference; 23 | import com.fasterxml.jackson.databind.JsonNode; 24 | import com.fasterxml.jackson.databind.ObjectMapper; 25 | 26 | /** 27 | * TODO 28 | * This class is a straight copy from Spring Security. 29 | * It should be consolidated when merging this codebase into Spring Security. 30 | * 31 | * Utility class for {@code JsonNode}. 32 | * 33 | * @author Joe Grandja 34 | * @since 5.3 35 | */ 36 | abstract class JsonNodeUtils { 37 | 38 | static final TypeReference> STRING_SET = new TypeReference>() { 39 | }; 40 | 41 | static final TypeReference> STRING_OBJECT_MAP = new TypeReference>() { 42 | }; 43 | 44 | static String findStringValue(JsonNode jsonNode, String fieldName) { 45 | if (jsonNode == null) { 46 | return null; 47 | } 48 | JsonNode value = jsonNode.findValue(fieldName); 49 | return (value != null && value.isTextual()) ? value.asText() : null; 50 | } 51 | 52 | static T findValue(JsonNode jsonNode, String fieldName, TypeReference valueTypeReference, 53 | ObjectMapper mapper) { 54 | if (jsonNode == null) { 55 | return null; 56 | } 57 | JsonNode value = jsonNode.findValue(fieldName); 58 | return (value != null && value.isContainerNode()) ? mapper.convertValue(value, valueTypeReference) : null; 59 | } 60 | 61 | static JsonNode findObjectNode(JsonNode jsonNode, String fieldName) { 62 | if (jsonNode == null) { 63 | return null; 64 | } 65 | JsonNode value = jsonNode.findValue(fieldName); 66 | return (value != null && value.isObject()) ? value : null; 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientCredentialsAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import java.util.Collections; 19 | import java.util.HashSet; 20 | import java.util.Map; 21 | import java.util.Set; 22 | 23 | import org.springframework.lang.Nullable; 24 | import org.springframework.security.core.Authentication; 25 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 26 | 27 | /** 28 | * An {@link Authentication} implementation used for the OAuth 2.0 Client Credentials Grant. 29 | * 30 | * @author Alexey Nesterov 31 | * @since 0.0.1 32 | * @see OAuth2AuthorizationGrantAuthenticationToken 33 | * @see OAuth2ClientCredentialsAuthenticationProvider 34 | */ 35 | public class OAuth2ClientCredentialsAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken { 36 | private final Set scopes; 37 | 38 | /** 39 | * Constructs an {@code OAuth2ClientCredentialsAuthenticationToken} using the provided parameters. 40 | * 41 | * @param clientPrincipal the authenticated client principal 42 | * @param scopes the requested scope(s) 43 | * @param additionalParameters the additional parameters 44 | */ 45 | public OAuth2ClientCredentialsAuthenticationToken(Authentication clientPrincipal, 46 | @Nullable Set scopes, @Nullable Map additionalParameters) { 47 | super(AuthorizationGrantType.CLIENT_CREDENTIALS, clientPrincipal, additionalParameters); 48 | this.scopes = Collections.unmodifiableSet( 49 | scopes != null ? new HashSet<>(scopes) : Collections.emptySet()); 50 | } 51 | 52 | /** 53 | * Returns the requested scope(s). 54 | * 55 | * @return the requested scope(s), or an empty {@code Set} if not available 56 | */ 57 | public Set getScopes() { 58 | return this.scopes; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /samples/custom-consent-authorizationserver/src/main/java/sample/jose/Jwks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.jose; 17 | 18 | import java.security.KeyPair; 19 | import java.security.interfaces.ECPrivateKey; 20 | import java.security.interfaces.ECPublicKey; 21 | import java.security.interfaces.RSAPrivateKey; 22 | import java.security.interfaces.RSAPublicKey; 23 | import java.util.UUID; 24 | 25 | import javax.crypto.SecretKey; 26 | 27 | import com.nimbusds.jose.jwk.Curve; 28 | import com.nimbusds.jose.jwk.ECKey; 29 | import com.nimbusds.jose.jwk.OctetSequenceKey; 30 | import com.nimbusds.jose.jwk.RSAKey; 31 | 32 | /** 33 | * @author Joe Grandja 34 | */ 35 | public final class Jwks { 36 | 37 | private Jwks() { 38 | } 39 | 40 | public static RSAKey generateRsa() { 41 | KeyPair keyPair = KeyGeneratorUtils.generateRsaKey(); 42 | RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 43 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 44 | // @formatter:off 45 | return new RSAKey.Builder(publicKey) 46 | .privateKey(privateKey) 47 | .keyID(UUID.randomUUID().toString()) 48 | .build(); 49 | // @formatter:on 50 | } 51 | 52 | public static ECKey generateEc() { 53 | KeyPair keyPair = KeyGeneratorUtils.generateEcKey(); 54 | ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic(); 55 | ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate(); 56 | Curve curve = Curve.forECParameterSpec(publicKey.getParams()); 57 | // @formatter:off 58 | return new ECKey.Builder(curve, publicKey) 59 | .privateKey(privateKey) 60 | .keyID(UUID.randomUUID().toString()) 61 | .build(); 62 | // @formatter:on 63 | } 64 | 65 | public static OctetSequenceKey generateSecret() { 66 | SecretKey secretKey = KeyGeneratorUtils.generateSecretKey(); 67 | // @formatter:off 68 | return new OctetSequenceKey.Builder(secretKey) 69 | .keyID(UUID.randomUUID().toString()) 70 | .build(); 71 | // @formatter:on 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /samples/default-authorizationserver/src/main/java/sample/jose/Jwks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.jose; 17 | 18 | import java.security.KeyPair; 19 | import java.security.interfaces.ECPrivateKey; 20 | import java.security.interfaces.ECPublicKey; 21 | import java.security.interfaces.RSAPrivateKey; 22 | import java.security.interfaces.RSAPublicKey; 23 | import java.util.UUID; 24 | 25 | import javax.crypto.SecretKey; 26 | 27 | import com.nimbusds.jose.jwk.Curve; 28 | import com.nimbusds.jose.jwk.ECKey; 29 | import com.nimbusds.jose.jwk.OctetSequenceKey; 30 | import com.nimbusds.jose.jwk.RSAKey; 31 | 32 | /** 33 | * @author Joe Grandja 34 | * @since 0.1.0 35 | */ 36 | public final class Jwks { 37 | 38 | private Jwks() { 39 | } 40 | 41 | public static RSAKey generateRsa() { 42 | KeyPair keyPair = KeyGeneratorUtils.generateRsaKey(); 43 | RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); 44 | RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate(); 45 | // @formatter:off 46 | return new RSAKey.Builder(publicKey) 47 | .privateKey(privateKey) 48 | .keyID(UUID.randomUUID().toString()) 49 | .build(); 50 | // @formatter:on 51 | } 52 | 53 | public static ECKey generateEc() { 54 | KeyPair keyPair = KeyGeneratorUtils.generateEcKey(); 55 | ECPublicKey publicKey = (ECPublicKey) keyPair.getPublic(); 56 | ECPrivateKey privateKey = (ECPrivateKey) keyPair.getPrivate(); 57 | Curve curve = Curve.forECParameterSpec(publicKey.getParams()); 58 | // @formatter:off 59 | return new ECKey.Builder(curve, publicKey) 60 | .privateKey(privateKey) 61 | .keyID(UUID.randomUUID().toString()) 62 | .build(); 63 | // @formatter:on 64 | } 65 | 66 | public static OctetSequenceKey generateSecret() { 67 | SecretKey secretKey = KeyGeneratorUtils.generateSecretKey(); 68 | // @formatter:off 69 | return new OctetSequenceKey.Builder(secretKey) 70 | .keyID(UUID.randomUUID().toString()) 71 | .build(); 72 | // @formatter:on 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcProviderMetadataClaimAccessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.oidc; 17 | 18 | 19 | import java.util.List; 20 | 21 | import org.springframework.security.oauth2.core.ClaimAccessor; 22 | import org.springframework.security.oauth2.core.OAuth2AuthorizationServerMetadataClaimAccessor; 23 | import org.springframework.security.oauth2.jose.jws.JwsAlgorithm; 24 | import org.springframework.security.oauth2.jwt.Jwt; 25 | 26 | /** 27 | * A {@link ClaimAccessor} for the "claims" that can be returned 28 | * in the OpenID Provider Configuration Response. 29 | * 30 | * @author Daniel Garnier-Moiroux 31 | * @since 0.1.0 32 | * @see ClaimAccessor 33 | * @see OAuth2AuthorizationServerMetadataClaimAccessor 34 | * @see OidcProviderMetadataClaimNames 35 | * @see OidcProviderConfiguration 36 | * @see 3. OpenID Provider Metadata 37 | */ 38 | public interface OidcProviderMetadataClaimAccessor extends OAuth2AuthorizationServerMetadataClaimAccessor { 39 | 40 | /** 41 | * Returns the Subject Identifier types supported {@code (subject_types_supported)}. 42 | * 43 | * @return the Subject Identifier types supported 44 | */ 45 | default List getSubjectTypes() { 46 | return getClaimAsStringList(OidcProviderMetadataClaimNames.SUBJECT_TYPES_SUPPORTED); 47 | } 48 | 49 | /** 50 | * Returns the {@link JwsAlgorithm JWS} signing algorithms supported for the {@link OidcIdToken ID Token} 51 | * to encode the claims in a {@link Jwt} {@code (id_token_signing_alg_values_supported)}. 52 | * 53 | * @return the {@link JwsAlgorithm JWS} signing algorithms supported for the {@link OidcIdToken ID Token} 54 | */ 55 | default List getIdTokenSigningAlgorithms() { 56 | return getClaimAsStringList(OidcProviderMetadataClaimNames.ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/http/converter/HttpMessageConverters.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2018 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.oidc.http.converter; 17 | 18 | import org.springframework.http.converter.GenericHttpMessageConverter; 19 | import org.springframework.http.converter.HttpMessageConverter; 20 | import org.springframework.http.converter.json.GsonHttpMessageConverter; 21 | import org.springframework.http.converter.json.JsonbHttpMessageConverter; 22 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 23 | import org.springframework.util.ClassUtils; 24 | 25 | /** 26 | * TODO 27 | * This class is a straight copy from Spring Security. 28 | * It should be consolidated when merging this codebase into Spring Security. 29 | * 30 | * Utility methods for {@link HttpMessageConverter}'s. 31 | * 32 | * @author Joe Grandja 33 | * @since 5.1 34 | */ 35 | final class HttpMessageConverters { 36 | 37 | private static final boolean jackson2Present; 38 | 39 | private static final boolean gsonPresent; 40 | 41 | private static final boolean jsonbPresent; 42 | 43 | static { 44 | ClassLoader classLoader = HttpMessageConverters.class.getClassLoader(); 45 | jackson2Present = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", classLoader) 46 | && ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator", classLoader); 47 | gsonPresent = ClassUtils.isPresent("com.google.gson.Gson", classLoader); 48 | jsonbPresent = ClassUtils.isPresent("javax.json.bind.Jsonb", classLoader); 49 | } 50 | 51 | private HttpMessageConverters() { 52 | } 53 | 54 | static GenericHttpMessageConverter getJsonMessageConverter() { 55 | if (jackson2Present) { 56 | return new MappingJackson2HttpMessageConverter(); 57 | } 58 | if (gsonPresent) { 59 | return new GsonHttpMessageConverter(); 60 | } 61 | if (jsonbPresent) { 62 | return new JsonbHttpMessageConverter(); 63 | } 64 | return null; 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcAuthenticationProviderUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.oidc.authentication; 17 | 18 | import org.springframework.security.authentication.AuthenticationProvider; 19 | import org.springframework.security.oauth2.core.AbstractOAuth2Token; 20 | import org.springframework.security.oauth2.core.OAuth2RefreshToken; 21 | import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; 22 | import org.springframework.security.oauth2.core.OAuth2AuthorizationCode; 23 | 24 | /** 25 | * Utility methods for the OpenID Connect 1.0 {@link AuthenticationProvider}'s. 26 | * 27 | * @author Joe Grandja 28 | * @since 0.1.1 29 | */ 30 | final class OidcAuthenticationProviderUtils { 31 | 32 | private OidcAuthenticationProviderUtils() { 33 | } 34 | 35 | static OAuth2Authorization invalidate( 36 | OAuth2Authorization authorization, T token) { 37 | 38 | // @formatter:off 39 | OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization) 40 | .token(token, 41 | (metadata) -> 42 | metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)); 43 | 44 | if (OAuth2RefreshToken.class.isAssignableFrom(token.getClass())) { 45 | authorizationBuilder.token( 46 | authorization.getAccessToken().getToken(), 47 | (metadata) -> 48 | metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)); 49 | 50 | OAuth2Authorization.Token authorizationCode = 51 | authorization.getToken(OAuth2AuthorizationCode.class); 52 | if (authorizationCode != null && !authorizationCode.isInvalidated()) { 53 | authorizationBuilder.token( 54 | authorizationCode.getToken(), 55 | (metadata) -> 56 | metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)); 57 | } 58 | } 59 | // @formatter:on 60 | 61 | return authorizationBuilder.build(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/DelegatingAuthenticationConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.web.authentication; 17 | 18 | import java.util.Collections; 19 | import java.util.LinkedList; 20 | import java.util.List; 21 | 22 | import javax.servlet.http.HttpServletRequest; 23 | 24 | import org.springframework.lang.Nullable; 25 | import org.springframework.security.core.Authentication; 26 | import org.springframework.security.web.authentication.AuthenticationConverter; 27 | import org.springframework.util.Assert; 28 | 29 | /** 30 | * An {@link AuthenticationConverter} that simply delegates to it's 31 | * internal {@code List} of {@link AuthenticationConverter}(s). 32 | *

33 | * Each {@link AuthenticationConverter} is given a chance to 34 | * {@link AuthenticationConverter#convert(HttpServletRequest)} 35 | * with the first {@code non-null} {@link Authentication} being returned. 36 | * 37 | * @author Joe Grandja 38 | * @since 0.0.2 39 | * @see AuthenticationConverter 40 | */ 41 | public final class DelegatingAuthenticationConverter implements AuthenticationConverter { 42 | private final List converters; 43 | 44 | /** 45 | * Constructs a {@code DelegatingAuthenticationConverter} using the provided parameters. 46 | * 47 | * @param converters a {@code List} of {@link AuthenticationConverter}(s) 48 | */ 49 | public DelegatingAuthenticationConverter(List converters) { 50 | Assert.notEmpty(converters, "converters cannot be empty"); 51 | this.converters = Collections.unmodifiableList(new LinkedList<>(converters)); 52 | } 53 | 54 | @Nullable 55 | @Override 56 | public Authentication convert(HttpServletRequest request) { 57 | Assert.notNull(request, "request cannot be null"); 58 | for (AuthenticationConverter converter : this.converters) { 59 | Authentication authentication = converter.convert(request); 60 | if (authentication != null) { 61 | return authentication; 62 | } 63 | } 64 | return null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import java.util.Map; 19 | 20 | import org.springframework.lang.Nullable; 21 | import org.springframework.security.core.Authentication; 22 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 23 | import org.springframework.util.Assert; 24 | 25 | /** 26 | * An {@link Authentication} implementation used for the OAuth 2.0 Authorization Code Grant. 27 | * 28 | * @author Joe Grandja 29 | * @author Madhu Bhat 30 | * @author Daniel Garnier-Moiroux 31 | * @since 0.0.1 32 | * @see OAuth2AuthorizationGrantAuthenticationToken 33 | * @see OAuth2AuthorizationCodeAuthenticationProvider 34 | */ 35 | public class OAuth2AuthorizationCodeAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken { 36 | private final String code; 37 | private final String redirectUri; 38 | 39 | /** 40 | * Constructs an {@code OAuth2AuthorizationCodeAuthenticationToken} using the provided parameters. 41 | * 42 | * @param code the authorization code 43 | * @param clientPrincipal the authenticated client principal 44 | * @param redirectUri the redirect uri 45 | * @param additionalParameters the additional parameters 46 | */ 47 | public OAuth2AuthorizationCodeAuthenticationToken(String code, Authentication clientPrincipal, 48 | @Nullable String redirectUri, @Nullable Map additionalParameters) { 49 | super(AuthorizationGrantType.AUTHORIZATION_CODE, clientPrincipal, additionalParameters); 50 | Assert.hasText(code, "code cannot be empty"); 51 | this.code = code; 52 | this.redirectUri = redirectUri; 53 | } 54 | 55 | /** 56 | * Returns the authorization code. 57 | * 58 | * @return the authorization code 59 | */ 60 | public String getCode() { 61 | return this.code; 62 | } 63 | 64 | /** 65 | * Returns the redirect uri. 66 | * 67 | * @return the redirect uri 68 | */ 69 | @Nullable 70 | public String getRedirectUri() { 71 | return this.redirectUri; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/config/util/InMemoryXmlWebApplicationContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2012-2016 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.config.util; 17 | 18 | import org.springframework.beans.BeansException; 19 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 20 | import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; 21 | import org.springframework.context.ApplicationContext; 22 | import org.springframework.core.io.Resource; 23 | import org.springframework.security.util.InMemoryResource; 24 | import org.springframework.web.context.support.AbstractRefreshableWebApplicationContext; 25 | 26 | import static org.springframework.security.config.util.InMemoryXmlApplicationContext.BEANS_CLOSE; 27 | import static org.springframework.security.config.util.InMemoryXmlApplicationContext.BEANS_OPENING; 28 | import static org.springframework.security.config.util.InMemoryXmlApplicationContext.SPRING_SECURITY_VERSION; 29 | 30 | /** 31 | * TODO 32 | * This class is a straight copy from Spring Security. 33 | * It should be removed when merging this codebase into Spring Security. 34 | * 35 | * @author Joe Grandja 36 | */ 37 | public class InMemoryXmlWebApplicationContext extends AbstractRefreshableWebApplicationContext { 38 | private Resource inMemoryXml; 39 | 40 | public InMemoryXmlWebApplicationContext(String xml) { 41 | this(xml, SPRING_SECURITY_VERSION, null); 42 | } 43 | 44 | public InMemoryXmlWebApplicationContext(String xml, ApplicationContext parent) { 45 | this(xml, SPRING_SECURITY_VERSION, parent); 46 | } 47 | 48 | public InMemoryXmlWebApplicationContext(String xml, String secVersion, ApplicationContext parent) { 49 | String fullXml = BEANS_OPENING + secVersion + ".xsd'>\n" + xml + BEANS_CLOSE; 50 | inMemoryXml = new InMemoryResource(fullXml); 51 | setAllowBeanDefinitionOverriding(true); 52 | setParent(parent); 53 | } 54 | 55 | @Override 56 | protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException { 57 | XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory); 58 | reader.loadBeanDefinitions(new Resource[] { inMemoryXml }); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/java/sample/config/WebClientConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.config; 17 | 18 | import org.springframework.context.annotation.Bean; 19 | import org.springframework.context.annotation.Configuration; 20 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; 21 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; 22 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; 23 | import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; 24 | import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; 25 | import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; 26 | import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; 27 | import org.springframework.web.reactive.function.client.WebClient; 28 | 29 | /** 30 | * @author Joe Grandja 31 | * @since 0.0.1 32 | */ 33 | @Configuration 34 | public class WebClientConfig { 35 | 36 | @Bean 37 | WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { 38 | ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = 39 | new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); 40 | return WebClient.builder() 41 | .apply(oauth2Client.oauth2Configuration()) 42 | .build(); 43 | } 44 | 45 | @Bean 46 | OAuth2AuthorizedClientManager authorizedClientManager( 47 | ClientRegistrationRepository clientRegistrationRepository, 48 | OAuth2AuthorizedClientRepository authorizedClientRepository) { 49 | 50 | OAuth2AuthorizedClientProvider authorizedClientProvider = 51 | OAuth2AuthorizedClientProviderBuilder.builder() 52 | .authorizationCode() 53 | .refreshToken() 54 | .clientCredentials() 55 | .build(); 56 | DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( 57 | clientRegistrationRepository, authorizedClientRepository); 58 | authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); 59 | 60 | return authorizedClientManager; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcUserInfoAuthenticationTokenTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.oidc.authentication; 17 | 18 | import java.util.Collections; 19 | 20 | import org.junit.Test; 21 | 22 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 23 | import org.springframework.security.oauth2.core.oidc.OidcUserInfo; 24 | import org.springframework.security.oauth2.core.oidc.StandardClaimNames; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 28 | 29 | /** 30 | * Tests for {@link OidcUserInfoAuthenticationToken}. 31 | * 32 | * @author Steve Riesenberg 33 | */ 34 | public class OidcUserInfoAuthenticationTokenTests { 35 | 36 | @Test 37 | public void constructorWhenPrincipalNullThenThrowIllegalArgumentException() { 38 | assertThatIllegalArgumentException() 39 | .isThrownBy(() -> new OidcUserInfoAuthenticationToken(null)) 40 | .withMessage("principal cannot be null"); 41 | } 42 | 43 | @Test 44 | public void constructorWhenPrincipalProvidedThenCreated() { 45 | UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(null, null); 46 | OidcUserInfoAuthenticationToken authentication = new OidcUserInfoAuthenticationToken(principal); 47 | assertThat(authentication.getPrincipal()).isEqualTo(principal); 48 | assertThat(authentication.getUserInfo()).isNull(); 49 | assertThat(authentication.isAuthenticated()).isFalse(); 50 | } 51 | 52 | @Test 53 | public void constructorWhenPrincipalAndUserInfoProvidedThenCreated() { 54 | UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(null, null); 55 | OidcUserInfo userInfo = new OidcUserInfo(Collections.singletonMap(StandardClaimNames.SUB, "user")); 56 | OidcUserInfoAuthenticationToken authentication = new OidcUserInfoAuthenticationToken(principal, userInfo); 57 | assertThat(authentication.getPrincipal()).isEqualTo(principal); 58 | assertThat(authentication.getUserInfo()).isEqualTo(userInfo); 59 | assertThat(authentication.isAuthenticated()).isTrue(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/authentication/OAuth2AuthenticationContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.authentication; 17 | 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | import org.springframework.lang.Nullable; 22 | import org.springframework.security.core.Authentication; 23 | import org.springframework.security.oauth2.core.context.Context; 24 | import org.springframework.util.Assert; 25 | import org.springframework.util.CollectionUtils; 26 | 27 | /** 28 | * A context that holds an {@link Authentication} and (optionally) additional information 29 | * and is used by an {@link OAuth2AuthenticationValidator} when attempting to validate the {@link Authentication}. 30 | * 31 | * @author Joe Grandja 32 | * @since 0.2.0 33 | * @see Context 34 | * @see OAuth2AuthenticationValidator 35 | */ 36 | public final class OAuth2AuthenticationContext implements Context { 37 | private final Map context; 38 | 39 | /** 40 | * Constructs an {@code OAuth2AuthenticationContext} using the provided parameters. 41 | * 42 | * @param authentication the {@code Authentication} 43 | * @param context a {@code Map} of additional context information 44 | */ 45 | public OAuth2AuthenticationContext(Authentication authentication, @Nullable Map context) { 46 | Assert.notNull(authentication, "authentication cannot be null"); 47 | this.context = new HashMap<>(); 48 | if (!CollectionUtils.isEmpty(context)) { 49 | this.context.putAll(context); 50 | } 51 | this.context.put(Authentication.class, authentication); 52 | } 53 | 54 | /** 55 | * Returns the {@link Authentication} associated to the authentication context. 56 | * 57 | * @param the type of the {@code Authentication} 58 | * @return the {@link Authentication} 59 | */ 60 | @SuppressWarnings("unchecked") 61 | public T getAuthentication() { 62 | return (T) get(Authentication.class); 63 | } 64 | 65 | @SuppressWarnings("unchecked") 66 | @Override 67 | public V get(Object key) { 68 | return (V) this.context.get(key); 69 | } 70 | 71 | @Override 72 | public boolean hasKey(Object key) { 73 | return this.context.containsKey(key); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/jose/TestJwks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.jose; 17 | 18 | import java.security.interfaces.ECPrivateKey; 19 | import java.security.interfaces.ECPublicKey; 20 | import java.security.interfaces.RSAPrivateKey; 21 | import java.security.interfaces.RSAPublicKey; 22 | 23 | import javax.crypto.SecretKey; 24 | 25 | import com.nimbusds.jose.jwk.Curve; 26 | import com.nimbusds.jose.jwk.ECKey; 27 | import com.nimbusds.jose.jwk.KeyUse; 28 | import com.nimbusds.jose.jwk.OctetSequenceKey; 29 | import com.nimbusds.jose.jwk.RSAKey; 30 | 31 | /** 32 | * @author Joe Grandja 33 | */ 34 | public final class TestJwks { 35 | 36 | // @formatter:off 37 | public static final RSAKey DEFAULT_RSA_JWK = 38 | jwk( 39 | TestKeys.DEFAULT_PUBLIC_KEY, 40 | TestKeys.DEFAULT_PRIVATE_KEY 41 | ).build(); 42 | // @formatter:on 43 | 44 | // @formatter:off 45 | public static final ECKey DEFAULT_EC_JWK = 46 | jwk( 47 | (ECPublicKey) TestKeys.DEFAULT_EC_KEY_PAIR.getPublic(), 48 | (ECPrivateKey) TestKeys.DEFAULT_EC_KEY_PAIR.getPrivate() 49 | ).build(); 50 | // @formatter:on 51 | 52 | // @formatter:off 53 | public static final OctetSequenceKey DEFAULT_SECRET_JWK = 54 | jwk( 55 | TestKeys.DEFAULT_SECRET_KEY 56 | ).build(); 57 | // @formatter:on 58 | 59 | private TestJwks() { 60 | } 61 | 62 | public static RSAKey.Builder jwk(RSAPublicKey publicKey, RSAPrivateKey privateKey) { 63 | // @formatter:off 64 | return new RSAKey.Builder(publicKey) 65 | .privateKey(privateKey) 66 | .keyUse(KeyUse.SIGNATURE) 67 | .keyID("rsa-jwk-kid"); 68 | // @formatter:on 69 | } 70 | 71 | public static ECKey.Builder jwk(ECPublicKey publicKey, ECPrivateKey privateKey) { 72 | // @formatter:off 73 | Curve curve = Curve.forECParameterSpec(publicKey.getParams()); 74 | return new ECKey.Builder(curve, publicKey) 75 | .privateKey(privateKey) 76 | .keyUse(KeyUse.SIGNATURE) 77 | .keyID("ec-jwk-kid"); 78 | // @formatter:on 79 | } 80 | 81 | public static OctetSequenceKey.Builder jwk(SecretKey secretKey) { 82 | // @formatter:off 83 | return new OctetSequenceKey.Builder(secretKey) 84 | .keyUse(KeyUse.SIGNATURE) 85 | .keyID("secret-jwk-kid"); 86 | // @formatter:on 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import java.util.Collections; 19 | import java.util.HashSet; 20 | import java.util.Map; 21 | import java.util.Set; 22 | 23 | import org.springframework.lang.Nullable; 24 | import org.springframework.security.core.Authentication; 25 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 26 | import org.springframework.util.Assert; 27 | 28 | /** 29 | * An {@link Authentication} implementation used for the OAuth 2.0 Refresh Token Grant. 30 | * 31 | * @author Alexey Nesterov 32 | * @since 0.0.3 33 | * @see OAuth2AuthorizationGrantAuthenticationToken 34 | * @see OAuth2RefreshTokenAuthenticationProvider 35 | */ 36 | public class OAuth2RefreshTokenAuthenticationToken extends OAuth2AuthorizationGrantAuthenticationToken { 37 | private final String refreshToken; 38 | private final Set scopes; 39 | 40 | /** 41 | * Constructs an {@code OAuth2RefreshTokenAuthenticationToken} using the provided parameters. 42 | * 43 | * @param refreshToken the refresh token 44 | * @param clientPrincipal the authenticated client principal 45 | * @param scopes the requested scope(s) 46 | * @param additionalParameters the additional parameters 47 | */ 48 | public OAuth2RefreshTokenAuthenticationToken(String refreshToken, Authentication clientPrincipal, 49 | @Nullable Set scopes, @Nullable Map additionalParameters) { 50 | super(AuthorizationGrantType.REFRESH_TOKEN, clientPrincipal, additionalParameters); 51 | Assert.hasText(refreshToken, "refreshToken cannot be empty"); 52 | this.refreshToken = refreshToken; 53 | this.scopes = Collections.unmodifiableSet( 54 | scopes != null ? new HashSet<>(scopes) : Collections.emptySet()); 55 | } 56 | 57 | /** 58 | * Returns the refresh token. 59 | * 60 | * @return the refresh token 61 | */ 62 | public String getRefreshToken() { 63 | return this.refreshToken; 64 | } 65 | 66 | /** 67 | * Returns the requested scope(s). 68 | * 69 | * @return the requested scope(s), or an empty {@code Set} if not available 70 | */ 71 | public Set getScopes() { 72 | return this.scopes; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2ModuleTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.jackson2; 17 | 18 | import java.util.Arrays; 19 | import java.util.Collections; 20 | import java.util.HashMap; 21 | import java.util.HashSet; 22 | import java.util.LinkedHashSet; 23 | import java.util.Map; 24 | import java.util.Set; 25 | 26 | import com.fasterxml.jackson.core.type.TypeReference; 27 | import com.fasterxml.jackson.databind.ObjectMapper; 28 | import org.junit.Before; 29 | import org.junit.Test; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | /** 34 | * Tests for {@link OAuth2AuthorizationServerJackson2Module}. 35 | * 36 | * @author Steve Riesenberg 37 | */ 38 | public class OAuth2AuthorizationServerJackson2ModuleTests { 39 | 40 | private static final TypeReference> STRING_OBJECT_MAP = new TypeReference>() { 41 | }; 42 | private static final TypeReference> STRING_SET = new TypeReference>() { 43 | }; 44 | 45 | private ObjectMapper objectMapper; 46 | 47 | @Before 48 | public void setup() { 49 | this.objectMapper = new ObjectMapper(); 50 | this.objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module()); 51 | } 52 | 53 | @Test 54 | public void readValueWhenUnmodifiableMapThenSuccess() throws Exception { 55 | Map map = Collections.unmodifiableMap(new HashMap<>(Collections.singletonMap("key", "value"))); 56 | String json = this.objectMapper.writeValueAsString(map); 57 | assertThat(this.objectMapper.readValue(json, STRING_OBJECT_MAP)).isEqualTo(map); 58 | } 59 | 60 | @Test 61 | public void readValueWhenHashSetThenSuccess() throws Exception { 62 | Set set = new HashSet<>(Arrays.asList("one", "two")); 63 | String json = this.objectMapper.writeValueAsString(set); 64 | assertThat(this.objectMapper.readValue(json, STRING_SET)).isEqualTo(set); 65 | } 66 | 67 | // gh-457 68 | @Test 69 | public void readValueWhenLinkedHashSetThenSuccess() throws Exception { 70 | Set set = new LinkedHashSet<>(Arrays.asList("one", "two")); 71 | String json = this.objectMapper.writeValueAsString(set); 72 | assertThat(this.objectMapper.readValue(json, STRING_SET)).isEqualTo(set); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2EndpointUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.web.authentication; 17 | 18 | import java.util.Map; 19 | 20 | import javax.servlet.http.HttpServletRequest; 21 | 22 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 23 | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; 24 | import org.springframework.security.oauth2.core.OAuth2Error; 25 | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; 26 | import org.springframework.security.oauth2.core.endpoint.PkceParameterNames; 27 | import org.springframework.util.LinkedMultiValueMap; 28 | import org.springframework.util.MultiValueMap; 29 | 30 | /** 31 | * Utility methods for the OAuth 2.0 Protocol Endpoints. 32 | * 33 | * @author Joe Grandja 34 | * @since 0.1.2 35 | */ 36 | final class OAuth2EndpointUtils { 37 | static final String ACCESS_TOKEN_REQUEST_ERROR_URI = "https://datatracker.ietf.org/doc/html/rfc6749#section-5.2"; 38 | 39 | private OAuth2EndpointUtils() { 40 | } 41 | 42 | static MultiValueMap getParameters(HttpServletRequest request) { 43 | Map parameterMap = request.getParameterMap(); 44 | MultiValueMap parameters = new LinkedMultiValueMap<>(parameterMap.size()); 45 | parameterMap.forEach((key, values) -> { 46 | if (values.length > 0) { 47 | for (String value : values) { 48 | parameters.add(key, value); 49 | } 50 | } 51 | }); 52 | return parameters; 53 | } 54 | 55 | static boolean matchesAuthorizationCodeGrantRequest(HttpServletRequest request) { 56 | return AuthorizationGrantType.AUTHORIZATION_CODE.getValue().equals( 57 | request.getParameter(OAuth2ParameterNames.GRANT_TYPE)) && 58 | request.getParameter(OAuth2ParameterNames.CODE) != null; 59 | } 60 | 61 | static boolean matchesPkceTokenRequest(HttpServletRequest request) { 62 | return matchesAuthorizationCodeGrantRequest(request) && 63 | request.getParameter(PkceParameterNames.CODE_VERIFIER) != null; 64 | } 65 | 66 | static void throwError(String errorCode, String parameterName, String errorUri) { 67 | OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, errorUri); 68 | throw new OAuth2AuthenticationException(error); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/JwtUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.oidc.authentication; 17 | 18 | import java.time.Instant; 19 | import java.util.Collections; 20 | import java.util.Set; 21 | 22 | import org.springframework.security.authentication.AuthenticationProvider; 23 | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; 24 | import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; 25 | import org.springframework.security.oauth2.jwt.JoseHeader; 26 | import org.springframework.security.oauth2.jwt.Jwt; 27 | import org.springframework.security.oauth2.jwt.JwtClaimsSet; 28 | import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; 29 | import org.springframework.util.CollectionUtils; 30 | import org.springframework.util.StringUtils; 31 | 32 | /** 33 | * TODO 34 | * This class is mostly a straight copy from {@code org.springframework.security.oauth2.server.authorization.authentication.JwtUtils}. 35 | * It should be consolidated when we introduce a token generator abstraction. 36 | * 37 | * Utility methods used by the {@link AuthenticationProvider}'s when issuing {@link Jwt}'s. 38 | * 39 | * @author Ovidiu Popa 40 | * @since 0.2.1 41 | */ 42 | final class JwtUtils { 43 | 44 | private JwtUtils() { 45 | } 46 | 47 | static JoseHeader.Builder headers() { 48 | return JoseHeader.withAlgorithm(SignatureAlgorithm.RS256); 49 | } 50 | 51 | static JwtClaimsSet.Builder accessTokenClaims(RegisteredClient registeredClient, 52 | String issuer, String subject, Set authorizedScopes) { 53 | 54 | Instant issuedAt = Instant.now(); 55 | Instant expiresAt = issuedAt.plus(registeredClient.getTokenSettings().getAccessTokenTimeToLive()); 56 | 57 | // @formatter:off 58 | JwtClaimsSet.Builder claimsBuilder = JwtClaimsSet.builder(); 59 | if (StringUtils.hasText(issuer)) { 60 | claimsBuilder.issuer(issuer); 61 | } 62 | claimsBuilder 63 | .subject(subject) 64 | .audience(Collections.singletonList(registeredClient.getClientId())) 65 | .issuedAt(issuedAt) 66 | .expiresAt(expiresAt) 67 | .notBefore(issuedAt); 68 | if (!CollectionUtils.isEmpty(authorizedScopes)) { 69 | claimsBuilder.claim(OAuth2ParameterNames.SCOPE, authorizedScopes); 70 | } 71 | // @formatter:on 72 | 73 | return claimsBuilder; 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/client/TestRegisteredClients.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.client; 17 | 18 | import java.time.Instant; 19 | import java.time.temporal.ChronoUnit; 20 | 21 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 22 | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; 23 | import org.springframework.security.oauth2.server.authorization.config.ClientSettings; 24 | 25 | /** 26 | * @author Anoop Garlapati 27 | */ 28 | public class TestRegisteredClients { 29 | 30 | public static RegisteredClient.Builder registeredClient() { 31 | return RegisteredClient.withId("registration-1") 32 | .clientId("client-1") 33 | .clientIdIssuedAt(Instant.now().truncatedTo(ChronoUnit.SECONDS)) 34 | .clientSecret("secret") 35 | .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) 36 | .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) 37 | .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) 38 | .redirectUri("https://example.com") 39 | .scope("scope1"); 40 | } 41 | 42 | public static RegisteredClient.Builder registeredClient2() { 43 | return RegisteredClient.withId("registration-2") 44 | .clientId("client-2") 45 | .clientIdIssuedAt(Instant.now().truncatedTo(ChronoUnit.SECONDS)) 46 | .clientSecret("secret") 47 | .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) 48 | .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN) 49 | .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) 50 | .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) 51 | .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST) 52 | .redirectUri("https://example.com") 53 | .scope("scope1") 54 | .scope("scope2"); 55 | } 56 | 57 | public static RegisteredClient.Builder registeredPublicClient() { 58 | return RegisteredClient.withId("registration-3") 59 | .clientId("client-3") 60 | .clientIdIssuedAt(Instant.now().truncatedTo(ChronoUnit.SECONDS)) 61 | .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) 62 | .clientAuthenticationMethod(ClientAuthenticationMethod.NONE) 63 | .redirectUri("https://example.com") 64 | .scope("scope1") 65 | .clientSettings(ClientSettings.builder().requireProofKey(true).build()); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationServerMetadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core; 17 | 18 | import java.util.Map; 19 | 20 | import org.springframework.util.Assert; 21 | 22 | /** 23 | * A representation of an OAuth 2.0 Authorization Server Metadata response, 24 | * which is returned from an OAuth 2.0 Authorization Server's Metadata Endpoint, 25 | * and contains a set of claims about the Authorization Server's configuration. 26 | * The claims are defined by the OAuth 2.0 Authorization Server Metadata 27 | * specification (RFC 8414). 28 | * 29 | * @author Daniel Garnier-Moiroux 30 | * @since 0.1.1 31 | * @see AbstractOAuth2AuthorizationServerMetadata 32 | * @see 3.2. Authorization Server Metadata Response 33 | */ 34 | public final class OAuth2AuthorizationServerMetadata extends AbstractOAuth2AuthorizationServerMetadata { 35 | 36 | private OAuth2AuthorizationServerMetadata(Map claims) { 37 | super(claims); 38 | } 39 | 40 | /** 41 | * Constructs a new {@link Builder} with empty claims. 42 | * 43 | * @return the {@link Builder} 44 | */ 45 | public static Builder builder() { 46 | return new Builder(); 47 | } 48 | 49 | /** 50 | * Constructs a new {@link Builder} with the provided claims. 51 | * 52 | * @param claims the claims to initialize the builder 53 | * @return the {@link Builder} 54 | */ 55 | public static Builder withClaims(Map claims) { 56 | Assert.notEmpty(claims, "claims cannot be empty"); 57 | return new Builder() 58 | .claims(c -> c.putAll(claims)); 59 | } 60 | 61 | /** 62 | * Helps configure an {@link OAuth2AuthorizationServerMetadata}. 63 | */ 64 | public static class Builder extends AbstractBuilder { 65 | 66 | private Builder() { 67 | } 68 | 69 | /** 70 | * Validate the claims and build the {@link OAuth2AuthorizationServerMetadata}. 71 | *

72 | * The following claims are REQUIRED: 73 | * {@code issuer}, {@code authorization_endpoint}, {@code token_endpoint} 74 | * and {@code response_types_supported}. 75 | * 76 | * @return the {@link OAuth2AuthorizationServerMetadata} 77 | */ 78 | @Override 79 | public OAuth2AuthorizationServerMetadata build() { 80 | validate(); 81 | return new OAuth2AuthorizationServerMetadata(getClaims()); 82 | } 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /samples/custom-consent-authorizationserver/src/main/java/sample/jose/KeyGeneratorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.jose; 17 | 18 | import java.math.BigInteger; 19 | import java.security.KeyPair; 20 | import java.security.KeyPairGenerator; 21 | import java.security.spec.ECFieldFp; 22 | import java.security.spec.ECParameterSpec; 23 | import java.security.spec.ECPoint; 24 | import java.security.spec.EllipticCurve; 25 | 26 | import javax.crypto.KeyGenerator; 27 | import javax.crypto.SecretKey; 28 | 29 | /** 30 | * @author Joe Grandja 31 | */ 32 | final class KeyGeneratorUtils { 33 | 34 | private KeyGeneratorUtils() { 35 | } 36 | 37 | static SecretKey generateSecretKey() { 38 | SecretKey hmacKey; 39 | try { 40 | hmacKey = KeyGenerator.getInstance("HmacSha256").generateKey(); 41 | } catch (Exception ex) { 42 | throw new IllegalStateException(ex); 43 | } 44 | return hmacKey; 45 | } 46 | 47 | static KeyPair generateRsaKey() { 48 | KeyPair keyPair; 49 | try { 50 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 51 | keyPairGenerator.initialize(2048); 52 | keyPair = keyPairGenerator.generateKeyPair(); 53 | } catch (Exception ex) { 54 | throw new IllegalStateException(ex); 55 | } 56 | return keyPair; 57 | } 58 | 59 | static KeyPair generateEcKey() { 60 | EllipticCurve ellipticCurve = new EllipticCurve( 61 | new ECFieldFp( 62 | new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951")), 63 | new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853948"), 64 | new BigInteger("41058363725152142129326129780047268409114441015993725554835256314039467401291")); 65 | ECPoint ecPoint = new ECPoint( 66 | new BigInteger("48439561293906451759052585252797914202762949526041747995844080717082404635286"), 67 | new BigInteger("36134250956749795798585127919587881956611106672985015071877198253568414405109")); 68 | ECParameterSpec ecParameterSpec = new ECParameterSpec( 69 | ellipticCurve, 70 | ecPoint, 71 | new BigInteger("115792089210356248762697446949407573529996955224135760342422259061068512044369"), 72 | 1); 73 | 74 | KeyPair keyPair; 75 | try { 76 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); 77 | keyPairGenerator.initialize(ecParameterSpec); 78 | keyPair = keyPairGenerator.generateKeyPair(); 79 | } catch (Exception ex) { 80 | throw new IllegalStateException(ex); 81 | } 82 | return keyPair; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /samples/default-authorizationserver/src/main/java/sample/jose/KeyGeneratorUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.jose; 17 | 18 | import java.math.BigInteger; 19 | import java.security.KeyPair; 20 | import java.security.KeyPairGenerator; 21 | import java.security.spec.ECFieldFp; 22 | import java.security.spec.ECParameterSpec; 23 | import java.security.spec.ECPoint; 24 | import java.security.spec.EllipticCurve; 25 | 26 | import javax.crypto.KeyGenerator; 27 | import javax.crypto.SecretKey; 28 | 29 | /** 30 | * @author Joe Grandja 31 | * @since 0.1.0 32 | */ 33 | final class KeyGeneratorUtils { 34 | 35 | private KeyGeneratorUtils() { 36 | } 37 | 38 | static SecretKey generateSecretKey() { 39 | SecretKey hmacKey; 40 | try { 41 | hmacKey = KeyGenerator.getInstance("HmacSha256").generateKey(); 42 | } catch (Exception ex) { 43 | throw new IllegalStateException(ex); 44 | } 45 | return hmacKey; 46 | } 47 | 48 | static KeyPair generateRsaKey() { 49 | KeyPair keyPair; 50 | try { 51 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA"); 52 | keyPairGenerator.initialize(2048); 53 | keyPair = keyPairGenerator.generateKeyPair(); 54 | } catch (Exception ex) { 55 | throw new IllegalStateException(ex); 56 | } 57 | return keyPair; 58 | } 59 | 60 | static KeyPair generateEcKey() { 61 | EllipticCurve ellipticCurve = new EllipticCurve( 62 | new ECFieldFp( 63 | new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853951")), 64 | new BigInteger("115792089210356248762697446949407573530086143415290314195533631308867097853948"), 65 | new BigInteger("41058363725152142129326129780047268409114441015993725554835256314039467401291")); 66 | ECPoint ecPoint = new ECPoint( 67 | new BigInteger("48439561293906451759052585252797914202762949526041747995844080717082404635286"), 68 | new BigInteger("36134250956749795798585127919587881956611106672985015071877198253568414405109")); 69 | ECParameterSpec ecParameterSpec = new ECParameterSpec( 70 | ellipticCurve, 71 | ecPoint, 72 | new BigInteger("115792089210356248762697446949407573529996955224135760342422259061068512044369"), 73 | 1); 74 | 75 | KeyPair keyPair; 76 | try { 77 | KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC"); 78 | keyPairGenerator.initialize(ecParameterSpec); 79 | keyPair = keyPairGenerator.generateKeyPair(); 80 | } catch (Exception ex) { 81 | throw new IllegalStateException(ex); 82 | } 83 | return keyPair; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/oidc/authentication/OidcUserInfoAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.oidc.authentication; 17 | 18 | import java.util.Collections; 19 | 20 | import org.springframework.security.authentication.AbstractAuthenticationToken; 21 | import org.springframework.security.core.Authentication; 22 | import org.springframework.security.oauth2.core.Version; 23 | import org.springframework.security.oauth2.core.oidc.OidcUserInfo; 24 | import org.springframework.util.Assert; 25 | 26 | /** 27 | * An {@link Authentication} implementation used for OpenID Connect 1.0 UserInfo Endpoint. 28 | * 29 | * @author Steve Riesenberg 30 | * @since 0.2.1 31 | * @see AbstractAuthenticationToken 32 | * @see OidcUserInfo 33 | * @see OidcUserInfoAuthenticationProvider 34 | */ 35 | public class OidcUserInfoAuthenticationToken extends AbstractAuthenticationToken { 36 | private static final long serialVersionUID = Version.SERIAL_VERSION_UID; 37 | private final Authentication principal; 38 | private final OidcUserInfo userInfo; 39 | 40 | /** 41 | * Constructs an {@code OidcUserInfoAuthenticationToken} using the provided parameters. 42 | * 43 | * @param principal the principal 44 | */ 45 | public OidcUserInfoAuthenticationToken(Authentication principal) { 46 | super(Collections.emptyList()); 47 | Assert.notNull(principal, "principal cannot be null"); 48 | this.principal = principal; 49 | this.userInfo = null; 50 | setAuthenticated(false); 51 | } 52 | 53 | /** 54 | * Constructs an {@code OidcUserInfoAuthenticationToken} using the provided parameters. 55 | * 56 | * @param principal the authenticated principal 57 | * @param userInfo the UserInfo claims 58 | */ 59 | public OidcUserInfoAuthenticationToken(Authentication principal, OidcUserInfo userInfo) { 60 | super(Collections.emptyList()); 61 | Assert.notNull(principal, "principal cannot be null"); 62 | Assert.notNull(userInfo, "userInfo cannot be null"); 63 | this.principal = principal; 64 | this.userInfo = userInfo; 65 | setAuthenticated(true); 66 | } 67 | 68 | @Override 69 | public Object getPrincipal() { 70 | return this.principal; 71 | } 72 | 73 | @Override 74 | public Object getCredentials() { 75 | return ""; 76 | } 77 | 78 | /** 79 | * Returns the UserInfo claims. 80 | * 81 | * @return the UserInfo claims 82 | */ 83 | public OidcUserInfo getUserInfo() { 84 | return this.userInfo; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Spring Security OAuth 2.0 Sample 5 | 6 | 7 | 8 | 9 | 10 | 11 |

12 | 20 |
21 |
22 | 26 |
27 |
28 |

Authorize the client using grant_type:

29 |
30 | 38 | 48 |
49 |
50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/config/annotation/web/configuration/RegisterMissingBeanPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.config.annotation.web.configuration; 18 | 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.function.Supplier; 22 | 23 | import org.springframework.beans.BeansException; 24 | import org.springframework.beans.factory.BeanFactory; 25 | import org.springframework.beans.factory.BeanFactoryAware; 26 | import org.springframework.beans.factory.BeanFactoryUtils; 27 | import org.springframework.beans.factory.ListableBeanFactory; 28 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 29 | import org.springframework.beans.factory.support.AbstractBeanDefinition; 30 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 31 | import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; 32 | import org.springframework.beans.factory.support.RootBeanDefinition; 33 | import org.springframework.context.annotation.AnnotationBeanNameGenerator; 34 | 35 | /** 36 | * Post processor to register one or more bean definitions on container initialization, if not already present. 37 | * 38 | * @author Steve Riesenberg 39 | * @since 0.2.0 40 | */ 41 | final class RegisterMissingBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware { 42 | private final AnnotationBeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); 43 | private final List beanDefinitions = new ArrayList<>(); 44 | private BeanFactory beanFactory; 45 | 46 | @Override 47 | public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { 48 | for (AbstractBeanDefinition beanDefinition : this.beanDefinitions) { 49 | String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( 50 | (ListableBeanFactory) this.beanFactory, beanDefinition.getBeanClass(), false, false); 51 | if (beanNames.length == 0) { 52 | String beanName = this.beanNameGenerator.generateBeanName(beanDefinition, registry); 53 | registry.registerBeanDefinition(beanName, beanDefinition); 54 | } 55 | } 56 | } 57 | 58 | @Override 59 | public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 60 | } 61 | 62 | void addBeanDefinition(Class beanClass, Supplier beanSupplier) { 63 | this.beanDefinitions.add(new RootBeanDefinition(beanClass, beanSupplier)); 64 | } 65 | 66 | @Override 67 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 68 | this.beanFactory = beanFactory; 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/OAuth2TokenIntrospectionClaimNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2002-2019 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.springframework.security.oauth2.core; 18 | 19 | /* 20 | * TODO 21 | * This class is "mostly" a copy from Spring Security and should be removed after upgrading to Spring Security 5.6.0 GA. 22 | * The major changes made between the Spring Security class and this one are: 23 | * 1) Class renamed from `OAuth2IntrospectionClaimNames` to `OAuth2TokenIntrospectionClaimNames` 24 | * 2) Moved from package `org.springframework.security.oauth2.server.resource.introspection` to `org.springframework.security.oauth2.core` 25 | * 26 | * gh-9647 Move and rename OAuth2IntrospectionClaimAccessor/Names 27 | * https://github.com/spring-projects/spring-security/issues/9647 28 | */ 29 | 30 | /** 31 | * The names of the "Introspection Claims" defined by an 32 | * Introspection 33 | * Response. 34 | * 35 | * @author Josh Cummings 36 | * @since 5.2 37 | */ 38 | public interface OAuth2TokenIntrospectionClaimNames { 39 | 40 | /** 41 | * {@code active} - Indicator whether or not the token is currently active 42 | */ 43 | String ACTIVE = "active"; 44 | 45 | /** 46 | * {@code scope} - The scopes for the token 47 | */ 48 | String SCOPE = "scope"; 49 | 50 | /** 51 | * {@code client_id} - The Client identifier for the token 52 | */ 53 | String CLIENT_ID = "client_id"; 54 | 55 | /** 56 | * {@code username} - A human-readable identifier for the resource owner that 57 | * authorized the token 58 | */ 59 | String USERNAME = "username"; 60 | 61 | /** 62 | * {@code token_type} - The type of the token, for example {@code bearer}. 63 | */ 64 | String TOKEN_TYPE = "token_type"; 65 | 66 | /** 67 | * {@code exp} - A timestamp indicating when the token expires 68 | */ 69 | String EXP = "exp"; 70 | 71 | /** 72 | * {@code iat} - A timestamp indicating when the token was issued 73 | */ 74 | String IAT = "iat"; 75 | 76 | /** 77 | * {@code nbf} - A timestamp indicating when the token is not to be used before 78 | */ 79 | String NBF = "nbf"; 80 | 81 | /** 82 | * {@code sub} - Usually a machine-readable identifier of the resource owner who 83 | * authorized the token 84 | */ 85 | String SUB = "sub"; 86 | 87 | /** 88 | * {@code aud} - The intended audience for the token 89 | */ 90 | String AUD = "aud"; 91 | 92 | /** 93 | * {@code iss} - The issuer of the token 94 | */ 95 | String ISS = "iss"; 96 | 97 | /** 98 | * {@code jti} - The identifier for the token 99 | */ 100 | String JTI = "jti"; 101 | 102 | } 103 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthenticationProviderUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import org.springframework.security.authentication.AuthenticationProvider; 19 | import org.springframework.security.core.Authentication; 20 | import org.springframework.security.oauth2.core.AbstractOAuth2Token; 21 | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; 22 | import org.springframework.security.oauth2.core.OAuth2AuthorizationCode; 23 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 24 | import org.springframework.security.oauth2.core.OAuth2RefreshToken; 25 | import org.springframework.security.oauth2.server.authorization.OAuth2Authorization; 26 | 27 | /** 28 | * Utility methods for the OAuth 2.0 {@link AuthenticationProvider}'s. 29 | * 30 | * @author Joe Grandja 31 | * @since 0.0.3 32 | */ 33 | final class OAuth2AuthenticationProviderUtils { 34 | 35 | private OAuth2AuthenticationProviderUtils() { 36 | } 37 | 38 | static OAuth2ClientAuthenticationToken getAuthenticatedClientElseThrowInvalidClient(Authentication authentication) { 39 | OAuth2ClientAuthenticationToken clientPrincipal = null; 40 | if (OAuth2ClientAuthenticationToken.class.isAssignableFrom(authentication.getPrincipal().getClass())) { 41 | clientPrincipal = (OAuth2ClientAuthenticationToken) authentication.getPrincipal(); 42 | } 43 | if (clientPrincipal != null && clientPrincipal.isAuthenticated()) { 44 | return clientPrincipal; 45 | } 46 | throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_CLIENT); 47 | } 48 | 49 | static OAuth2Authorization invalidate( 50 | OAuth2Authorization authorization, T token) { 51 | 52 | // @formatter:off 53 | OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.from(authorization) 54 | .token(token, 55 | (metadata) -> 56 | metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)); 57 | 58 | if (OAuth2RefreshToken.class.isAssignableFrom(token.getClass())) { 59 | authorizationBuilder.token( 60 | authorization.getAccessToken().getToken(), 61 | (metadata) -> 62 | metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)); 63 | 64 | OAuth2Authorization.Token authorizationCode = 65 | authorization.getToken(OAuth2AuthorizationCode.class); 66 | if (authorizationCode != null && !authorizationCode.isInvalidated()) { 67 | authorizationBuilder.token( 68 | authorizationCode.getToken(), 69 | (metadata) -> 70 | metadata.put(OAuth2Authorization.Token.INVALIDATED_METADATA_NAME, true)); 71 | } 72 | } 73 | // @formatter:on 74 | 75 | return authorizationBuilder.build(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/PublicClientAuthenticationConverter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.web.authentication; 17 | 18 | import java.util.HashMap; 19 | 20 | import javax.servlet.http.HttpServletRequest; 21 | 22 | import org.springframework.lang.Nullable; 23 | import org.springframework.security.core.Authentication; 24 | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; 25 | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; 26 | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; 27 | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; 28 | import org.springframework.security.oauth2.core.endpoint.PkceParameterNames; 29 | import org.springframework.security.oauth2.server.authorization.authentication.OAuth2ClientAuthenticationToken; 30 | import org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter; 31 | import org.springframework.security.web.authentication.AuthenticationConverter; 32 | import org.springframework.util.MultiValueMap; 33 | import org.springframework.util.StringUtils; 34 | 35 | /** 36 | * Attempts to extract the parameters from {@link HttpServletRequest} 37 | * used for authenticating public clients using Proof Key for Code Exchange (PKCE). 38 | * 39 | * @author Joe Grandja 40 | * @since 0.0.2 41 | * @see AuthenticationConverter 42 | * @see OAuth2ClientAuthenticationToken 43 | * @see OAuth2ClientAuthenticationFilter 44 | * @see Proof Key for Code Exchange by OAuth Public Clients 45 | */ 46 | public final class PublicClientAuthenticationConverter implements AuthenticationConverter { 47 | 48 | @Nullable 49 | @Override 50 | public Authentication convert(HttpServletRequest request) { 51 | if (!OAuth2EndpointUtils.matchesPkceTokenRequest(request)) { 52 | return null; 53 | } 54 | 55 | MultiValueMap parameters = OAuth2EndpointUtils.getParameters(request); 56 | 57 | // client_id (REQUIRED for public clients) 58 | String clientId = parameters.getFirst(OAuth2ParameterNames.CLIENT_ID); 59 | if (!StringUtils.hasText(clientId) || 60 | parameters.get(OAuth2ParameterNames.CLIENT_ID).size() != 1) { 61 | throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST); 62 | } 63 | 64 | // code_verifier (REQUIRED) 65 | if (parameters.get(PkceParameterNames.CODE_VERIFIER).size() != 1) { 66 | throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST); 67 | } 68 | 69 | parameters.remove(OAuth2ParameterNames.CLIENT_ID); 70 | 71 | return new OAuth2ClientAuthenticationToken(clientId, ClientAuthenticationMethod.NONE, null, 72 | new HashMap<>(parameters.toSingleValueMap())); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/jackson2/OAuth2AuthorizationServerJackson2Module.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.jackson2; 17 | 18 | import java.time.Duration; 19 | import java.util.Collections; 20 | import java.util.HashSet; 21 | import java.util.LinkedHashSet; 22 | 23 | import com.fasterxml.jackson.core.Version; 24 | import com.fasterxml.jackson.databind.module.SimpleModule; 25 | 26 | import org.springframework.security.jackson2.SecurityJackson2Modules; 27 | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; 28 | import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm; 29 | 30 | /** 31 | * Jackson {@code Module} for {@code spring-authorization-server}, that registers the 32 | * following mix-in annotations: 33 | * 34 | *
    35 | *
  • {@link UnmodifiableMapMixin}
  • 36 | *
  • {@link HashSetMixin}
  • 37 | *
  • {@link OAuth2AuthorizationRequestMixin}
  • 38 | *
  • {@link DurationMixin}
  • 39 | *
  • {@link SignatureAlgorithmMixin}
  • 40 | *
41 | * 42 | * If not already enabled, default typing will be automatically enabled as type info is 43 | * required to properly serialize/deserialize objects. In order to use this module just 44 | * add it to your {@code ObjectMapper} configuration. 45 | * 46 | *
47 |  *     ObjectMapper mapper = new ObjectMapper();
48 |  *     mapper.registerModule(new OAuth2AuthorizationServerJackson2Module());
49 |  * 
50 | * 51 | * NOTE: Use {@link SecurityJackson2Modules#getModules(ClassLoader)} to get a list 52 | * of all security modules. 53 | * 54 | * @author Steve Riesenberg 55 | * @since 0.1.2 56 | * @see SecurityJackson2Modules 57 | * @see UnmodifiableMapMixin 58 | * @see HashSetMixin 59 | * @see OAuth2AuthorizationRequestMixin 60 | * @see DurationMixin 61 | * @see SignatureAlgorithmMixin 62 | */ 63 | public class OAuth2AuthorizationServerJackson2Module extends SimpleModule { 64 | 65 | public OAuth2AuthorizationServerJackson2Module() { 66 | super(OAuth2AuthorizationServerJackson2Module.class.getName(), new Version(1, 0, 0, null, null, null)); 67 | } 68 | 69 | @Override 70 | public void setupModule(SetupContext context) { 71 | SecurityJackson2Modules.enableDefaultTyping(context.getOwner()); 72 | context.setMixInAnnotations(Collections.unmodifiableMap(Collections.emptyMap()).getClass(), 73 | UnmodifiableMapMixin.class); 74 | context.setMixInAnnotations(HashSet.class, HashSetMixin.class); 75 | context.setMixInAnnotations(LinkedHashSet.class, HashSetMixin.class); 76 | context.setMixInAnnotations(OAuth2AuthorizationRequest.class, OAuth2AuthorizationRequestMixin.class); 77 | context.setMixInAnnotations(Duration.class, DurationMixin.class); 78 | context.setMixInAnnotations(SignatureAlgorithm.class, SignatureAlgorithmMixin.class); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | @rem Execute Gradle 88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 89 | 90 | :end 91 | @rem End local scope for the variables with windows NT shell 92 | if "%ERRORLEVEL%"=="0" goto mainEnd 93 | 94 | :fail 95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 96 | rem the _cmd.exe /c_ return code! 97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 98 | exit /b 1 99 | 100 | :mainEnd 101 | if "%OS%"=="Windows_NT" endlocal 102 | 103 | :omega 104 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import org.springframework.lang.Nullable; 19 | import org.springframework.security.core.Authentication; 20 | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; 21 | import org.springframework.security.oauth2.core.OAuth2Error; 22 | 23 | /** 24 | * This exception is thrown by {@link OAuth2AuthorizationCodeRequestAuthenticationProvider} 25 | * when an attempt to authenticate the OAuth 2.0 Authorization Request (or Consent) fails. 26 | * 27 | * @author Joe Grandja 28 | * @since 0.1.2 29 | * @see OAuth2AuthorizationCodeRequestAuthenticationToken 30 | * @see OAuth2AuthorizationCodeRequestAuthenticationProvider 31 | */ 32 | public class OAuth2AuthorizationCodeRequestAuthenticationException extends OAuth2AuthenticationException { 33 | private final OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication; 34 | 35 | /** 36 | * Constructs an {@code OAuth2AuthorizationCodeRequestAuthenticationException} using the provided parameters. 37 | * 38 | * @param error the {@link OAuth2Error OAuth 2.0 Error} 39 | * @param authorizationCodeRequestAuthentication the {@link Authentication} instance of the OAuth 2.0 Authorization Request (or Consent) 40 | */ 41 | public OAuth2AuthorizationCodeRequestAuthenticationException(OAuth2Error error, 42 | @Nullable OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication) { 43 | super(error); 44 | this.authorizationCodeRequestAuthentication = authorizationCodeRequestAuthentication; 45 | } 46 | 47 | /** 48 | * Constructs an {@code OAuth2AuthorizationCodeRequestAuthenticationException} using the provided parameters. 49 | * 50 | * @param error the {@link OAuth2Error OAuth 2.0 Error} 51 | * @param cause the root cause 52 | * @param authorizationCodeRequestAuthentication the {@link Authentication} instance of the OAuth 2.0 Authorization Request (or Consent) 53 | */ 54 | public OAuth2AuthorizationCodeRequestAuthenticationException(OAuth2Error error, Throwable cause, 55 | @Nullable OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication) { 56 | super(error, cause); 57 | this.authorizationCodeRequestAuthentication = authorizationCodeRequestAuthentication; 58 | } 59 | 60 | /** 61 | * Returns the {@link Authentication} instance of the OAuth 2.0 Authorization Request (or Consent), or {@code null} if not available. 62 | * 63 | * @return the {@link OAuth2AuthorizationCodeRequestAuthenticationToken} 64 | */ 65 | @Nullable 66 | public OAuth2AuthorizationCodeRequestAuthenticationToken getAuthorizationCodeRequestAuthentication() { 67 | return this.authorizationCodeRequestAuthentication; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationGrantAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import java.util.Collections; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import org.springframework.lang.Nullable; 23 | import org.springframework.security.authentication.AbstractAuthenticationToken; 24 | import org.springframework.security.core.Authentication; 25 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 26 | import org.springframework.security.oauth2.core.Version; 27 | import org.springframework.util.Assert; 28 | 29 | /** 30 | * Base implementation of an {@link Authentication} representing an OAuth 2.0 Authorization Grant. 31 | * 32 | * @author Joe Grandja 33 | * @since 0.1.0 34 | * @see AbstractAuthenticationToken 35 | * @see AuthorizationGrantType 36 | * @see OAuth2ClientAuthenticationToken 37 | * @see Section 1.3 Authorization Grant 38 | */ 39 | public class OAuth2AuthorizationGrantAuthenticationToken extends AbstractAuthenticationToken { 40 | private static final long serialVersionUID = Version.SERIAL_VERSION_UID; 41 | private final AuthorizationGrantType authorizationGrantType; 42 | private final Authentication clientPrincipal; 43 | private final Map additionalParameters; 44 | 45 | /** 46 | * Sub-class constructor. 47 | * 48 | * @param authorizationGrantType the authorization grant type 49 | * @param clientPrincipal the authenticated client principal 50 | * @param additionalParameters the additional parameters 51 | */ 52 | protected OAuth2AuthorizationGrantAuthenticationToken(AuthorizationGrantType authorizationGrantType, 53 | Authentication clientPrincipal, @Nullable Map additionalParameters) { 54 | super(Collections.emptyList()); 55 | Assert.notNull(authorizationGrantType, "authorizationGrantType cannot be null"); 56 | Assert.notNull(clientPrincipal, "clientPrincipal cannot be null"); 57 | this.authorizationGrantType = authorizationGrantType; 58 | this.clientPrincipal = clientPrincipal; 59 | this.additionalParameters = Collections.unmodifiableMap( 60 | additionalParameters != null ? 61 | new HashMap<>(additionalParameters) : 62 | Collections.emptyMap()); 63 | } 64 | 65 | /** 66 | * Returns the authorization grant type. 67 | * 68 | * @return the authorization grant type 69 | */ 70 | public AuthorizationGrantType getGrantType() { 71 | return this.authorizationGrantType; 72 | } 73 | 74 | @Override 75 | public Object getPrincipal() { 76 | return this.clientPrincipal; 77 | } 78 | 79 | @Override 80 | public Object getCredentials() { 81 | return ""; 82 | } 83 | 84 | /** 85 | * Returns the additional parameters. 86 | * 87 | * @return the additional parameters 88 | */ 89 | public Map getAdditionalParameters() { 90 | return this.additionalParameters; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/oidc/OidcClientMetadataClaimNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core.oidc; 17 | 18 | import org.springframework.security.oauth2.jose.jws.JwsAlgorithm; 19 | 20 | /** 21 | * The names of the "claims" defined by OpenID Connect Dynamic Client Registration 1.0 22 | * that are contained in the OpenID Client Registration Request and Response. 23 | * 24 | * @author Ovidiu Popa 25 | * @author Joe Grandja 26 | * @since 0.1.1 27 | * @see 2. Client Metadata 28 | */ 29 | public interface OidcClientMetadataClaimNames { 30 | 31 | /** 32 | * {@code client_id} - the Client Identifier 33 | */ 34 | String CLIENT_ID = "client_id"; 35 | 36 | /** 37 | * {@code client_id_issued_at} - the time at which the Client Identifier was issued 38 | */ 39 | String CLIENT_ID_ISSUED_AT = "client_id_issued_at"; 40 | 41 | /** 42 | * {@code client_secret} - the Client Secret 43 | */ 44 | String CLIENT_SECRET = "client_secret"; 45 | 46 | /** 47 | * {@code client_secret_expires_at} - the time at which the {@code client_secret} will expire or 0 if it will not expire 48 | */ 49 | String CLIENT_SECRET_EXPIRES_AT = "client_secret_expires_at"; 50 | 51 | /** 52 | * {@code client_name} - the name of the Client to be presented to the End-User 53 | */ 54 | String CLIENT_NAME = "client_name"; 55 | 56 | /** 57 | * {@code redirect_uris} - the redirection {@code URI} values used by the Client 58 | */ 59 | String REDIRECT_URIS = "redirect_uris"; 60 | 61 | /** 62 | * {@code token_endpoint_auth_method} - the authentication method used by the Client for the Token Endpoint 63 | */ 64 | String TOKEN_ENDPOINT_AUTH_METHOD = "token_endpoint_auth_method"; 65 | 66 | /** 67 | * {@code grant_types} - the OAuth 2.0 {@code grant_type} values that the Client will restrict itself to using 68 | */ 69 | String GRANT_TYPES = "grant_types"; 70 | 71 | /** 72 | * {@code response_types} - the OAuth 2.0 {@code response_type} values that the Client will restrict itself to using 73 | */ 74 | String RESPONSE_TYPES = "response_types"; 75 | 76 | /** 77 | * {@code scope} - a space-separated list of OAuth 2.0 {@code scope} values that the Client will restrict itself to using 78 | */ 79 | String SCOPE = "scope"; 80 | 81 | /** 82 | * {@code id_token_signed_response_alg} - the {@link JwsAlgorithm JWS} algorithm required for signing the {@link OidcIdToken ID Token} issued to the Client 83 | */ 84 | String ID_TOKEN_SIGNED_RESPONSE_ALG = "id_token_signed_response_alg"; 85 | 86 | /** 87 | * {@code registration_access_token} - the Registration Access Token that can be used at the Client Configuration Endpoint 88 | * @since 0.2.1 89 | */ 90 | String REGISTRATION_ACCESS_TOKEN = "registration_access_token"; 91 | 92 | /** 93 | * {@code registration_client_uri} - the {@code URL} of the Client Configuration Endpoint where the Registration Access Token can be used 94 | * @since 0.2.1 95 | */ 96 | String REGISTRATION_CLIENT_URI = "registration_client_uri"; 97 | 98 | } 99 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/config/util/InMemoryXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.config.util; 17 | 18 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 19 | import org.springframework.context.ApplicationContext; 20 | import org.springframework.context.support.AbstractXmlApplicationContext; 21 | import org.springframework.core.io.Resource; 22 | import org.springframework.security.util.InMemoryResource; 23 | 24 | /** 25 | * TODO 26 | * This class is a straight copy from Spring Security. 27 | * It should be removed when merging this codebase into Spring Security. 28 | * 29 | * @author Luke Taylor 30 | * @author Eddú Meléndez 31 | */ 32 | public class InMemoryXmlApplicationContext extends AbstractXmlApplicationContext { 33 | static final String BEANS_OPENING = "\n" + xml + BEANS_CLOSE; 62 | inMemoryXml = new InMemoryResource(fullXml); 63 | setAllowBeanDefinitionOverriding(true); 64 | setParent(parent); 65 | refresh(); 66 | } 67 | 68 | @Override 69 | protected DefaultListableBeanFactory createBeanFactory() { 70 | return new DefaultListableBeanFactory(getInternalParentBeanFactory()) { 71 | @Override 72 | protected boolean allowAliasOverriding() { 73 | return true; 74 | } 75 | }; 76 | } 77 | 78 | protected Resource[] getConfigResources() { 79 | return new Resource[] { inMemoryXml }; 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2RefreshTokenAuthenticationTokenTests.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import java.util.Collections; 19 | import java.util.Map; 20 | import java.util.Set; 21 | 22 | import org.junit.Test; 23 | 24 | import org.springframework.security.oauth2.core.AuthorizationGrantType; 25 | import org.springframework.security.oauth2.core.ClientAuthenticationMethod; 26 | import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; 27 | import org.springframework.security.oauth2.server.authorization.client.TestRegisteredClients; 28 | 29 | import static org.assertj.core.api.Assertions.assertThat; 30 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 31 | 32 | /** 33 | * Tests for {@link OAuth2RefreshTokenAuthenticationToken}. 34 | * 35 | * @author Alexey Nesterov 36 | * @since 0.0.3 37 | */ 38 | public class OAuth2RefreshTokenAuthenticationTokenTests { 39 | private RegisteredClient registeredClient = TestRegisteredClients.registeredClient().build(); 40 | private OAuth2ClientAuthenticationToken clientPrincipal = new OAuth2ClientAuthenticationToken( 41 | this.registeredClient, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, this.registeredClient.getClientSecret()); 42 | private Set scopes = Collections.singleton("scope1"); 43 | private Map additionalParameters = Collections.singletonMap("param1", "value1"); 44 | 45 | @Test 46 | public void constructorWhenRefreshTokenNullOrEmptyThenThrowIllegalArgumentException() { 47 | assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken(null, this.clientPrincipal, this.scopes, this.additionalParameters)) 48 | .isInstanceOf(IllegalArgumentException.class) 49 | .hasMessage("refreshToken cannot be empty"); 50 | assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("", this.clientPrincipal, this.scopes, this.additionalParameters)) 51 | .isInstanceOf(IllegalArgumentException.class) 52 | .hasMessage("refreshToken cannot be empty"); 53 | } 54 | 55 | @Test 56 | public void constructorWhenClientPrincipalNullThenThrowIllegalArgumentException() { 57 | assertThatThrownBy(() -> new OAuth2RefreshTokenAuthenticationToken("refresh-token", null, this.scopes, this.additionalParameters)) 58 | .isInstanceOf(IllegalArgumentException.class) 59 | .hasMessage("clientPrincipal cannot be null"); 60 | } 61 | 62 | @Test 63 | public void constructorWhenScopesProvidedThenCreated() { 64 | OAuth2RefreshTokenAuthenticationToken authentication = new OAuth2RefreshTokenAuthenticationToken( 65 | "refresh-token", this.clientPrincipal, this.scopes, this.additionalParameters); 66 | assertThat(authentication.getGrantType()).isEqualTo(AuthorizationGrantType.REFRESH_TOKEN); 67 | assertThat(authentication.getRefreshToken()).isEqualTo("refresh-token"); 68 | assertThat(authentication.getPrincipal()).isEqualTo(this.clientPrincipal); 69 | assertThat(authentication.getCredentials().toString()).isEmpty(); 70 | assertThat(authentication.getScopes()).isEqualTo(this.scopes); 71 | assertThat(authentication.getAdditionalParameters()).isEqualTo(this.additionalParameters); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /samples/messages-client/src/main/java/sample/web/AuthorizationController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package sample.web; 17 | 18 | import org.springframework.beans.factory.annotation.Value; 19 | import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; 20 | import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; 21 | import org.springframework.security.oauth2.core.OAuth2Error; 22 | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; 23 | import org.springframework.stereotype.Controller; 24 | import org.springframework.ui.Model; 25 | import org.springframework.util.StringUtils; 26 | import org.springframework.web.bind.annotation.GetMapping; 27 | import org.springframework.web.reactive.function.client.WebClient; 28 | 29 | import javax.servlet.http.HttpServletRequest; 30 | 31 | import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; 32 | import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; 33 | 34 | /** 35 | * @author Joe Grandja 36 | * @since 0.0.1 37 | */ 38 | @Controller 39 | public class AuthorizationController { 40 | private final WebClient webClient; 41 | private final String messagesBaseUri; 42 | 43 | public AuthorizationController(WebClient webClient, 44 | @Value("${messages.base-uri}") String messagesBaseUri) { 45 | this.webClient = webClient; 46 | this.messagesBaseUri = messagesBaseUri; 47 | } 48 | 49 | @GetMapping(value = "/authorize", params = "grant_type=authorization_code") 50 | public String authorizationCodeGrant(Model model, 51 | @RegisteredOAuth2AuthorizedClient("messaging-client-authorization-code") 52 | OAuth2AuthorizedClient authorizedClient) { 53 | 54 | String[] messages = this.webClient 55 | .get() 56 | .uri(this.messagesBaseUri) 57 | .attributes(oauth2AuthorizedClient(authorizedClient)) 58 | .retrieve() 59 | .bodyToMono(String[].class) 60 | .block(); 61 | model.addAttribute("messages", messages); 62 | 63 | return "index"; 64 | } 65 | 66 | // '/authorized' is the registered 'redirect_uri' for authorization_code 67 | @GetMapping(value = "/authorized", params = OAuth2ParameterNames.ERROR) 68 | public String authorizationFailed(Model model, HttpServletRequest request) { 69 | String errorCode = request.getParameter(OAuth2ParameterNames.ERROR); 70 | if (StringUtils.hasText(errorCode)) { 71 | model.addAttribute("error", 72 | new OAuth2Error( 73 | errorCode, 74 | request.getParameter(OAuth2ParameterNames.ERROR_DESCRIPTION), 75 | request.getParameter(OAuth2ParameterNames.ERROR_URI)) 76 | ); 77 | } 78 | 79 | return "index"; 80 | } 81 | 82 | @GetMapping(value = "/authorize", params = "grant_type=client_credentials") 83 | public String clientCredentialsGrant(Model model) { 84 | 85 | String[] messages = this.webClient 86 | .get() 87 | .uri(this.messagesBaseUri) 88 | .attributes(clientRegistrationId("messaging-client-client-credentials")) 89 | .retrieve() 90 | .bodyToMono(String[].class) 91 | .block(); 92 | model.addAttribute("messages", messages); 93 | 94 | return "index"; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/core/OAuth2AuthorizationServerMetadataClaimNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.core; 17 | 18 | /** 19 | * The names of the "claims" an Authorization Server describes about its configuration, 20 | * used in OAuth 2.0 Authorization Server Metadata and OpenID Connect Discovery 1.0. 21 | * 22 | * @author Daniel Garnier-Moiroux 23 | * @since 0.1.1 24 | * @see 2. Authorization Server Metadata 25 | * @see 3. OpenID Provider Metadata 26 | */ 27 | public interface OAuth2AuthorizationServerMetadataClaimNames { 28 | 29 | /** 30 | * {@code issuer} - the {@code URL} the Authorization Server asserts as its Issuer Identifier 31 | */ 32 | String ISSUER = "issuer"; 33 | 34 | /** 35 | * {@code authorization_endpoint} - the {@code URL} of the OAuth 2.0 Authorization Endpoint 36 | */ 37 | String AUTHORIZATION_ENDPOINT = "authorization_endpoint"; 38 | 39 | /** 40 | * {@code token_endpoint} - the {@code URL} of the OAuth 2.0 Token Endpoint 41 | */ 42 | String TOKEN_ENDPOINT = "token_endpoint"; 43 | 44 | /** 45 | * {@code token_endpoint_auth_methods_supported} - the client authentication methods supported by the OAuth 2.0 Token Endpoint 46 | */ 47 | String TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED = "token_endpoint_auth_methods_supported"; 48 | 49 | /** 50 | * {@code jwks_uri} - the {@code URL} of the JSON Web Key Set 51 | */ 52 | String JWKS_URI = "jwks_uri"; 53 | 54 | /** 55 | * {@code scopes_supported} - the OAuth 2.0 {@code scope} values supported 56 | */ 57 | String SCOPES_SUPPORTED = "scopes_supported"; 58 | 59 | /** 60 | * {@code response_types_supported} - the OAuth 2.0 {@code response_type} values supported 61 | */ 62 | String RESPONSE_TYPES_SUPPORTED = "response_types_supported"; 63 | 64 | /** 65 | * {@code grant_types_supported} - the OAuth 2.0 {@code grant_type} values supported 66 | */ 67 | String GRANT_TYPES_SUPPORTED = "grant_types_supported"; 68 | 69 | /** 70 | * {@code revocation_endpoint} - the {@code URL} of the OAuth 2.0 Token Revocation Endpoint 71 | */ 72 | String REVOCATION_ENDPOINT = "revocation_endpoint"; 73 | 74 | /** 75 | * {@code revocation_endpoint_auth_methods_supported} - the client authentication methods supported by the OAuth 2.0 Token Revocation Endpoint 76 | */ 77 | String REVOCATION_ENDPOINT_AUTH_METHODS_SUPPORTED = "revocation_endpoint_auth_methods_supported"; 78 | 79 | /** 80 | * {@code introspection_endpoint} - the {@code URL} of the OAuth 2.0 Token Introspection Endpoint 81 | */ 82 | String INTROSPECTION_ENDPOINT = "introspection_endpoint"; 83 | 84 | /** 85 | * {@code introspection_endpoint_auth_methods_supported} - the client authentication methods supported by the OAuth 2.0 Token Introspection Endpoint 86 | */ 87 | String INTROSPECTION_ENDPOINT_AUTH_METHODS_SUPPORTED = "introspection_endpoint_auth_methods_supported"; 88 | 89 | /** 90 | * {@code code_challenge_methods_supported} - the Proof Key for Code Exchange (PKCE) {@code code_challenge_method} values supported 91 | */ 92 | String CODE_CHALLENGE_METHODS_SUPPORTED = "code_challenge_methods_supported"; 93 | 94 | } 95 | -------------------------------------------------------------------------------- /oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2TokenRevocationAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020-2021 the original author or authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * https://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package org.springframework.security.oauth2.server.authorization.authentication; 17 | 18 | import java.util.Collections; 19 | 20 | import org.springframework.lang.Nullable; 21 | import org.springframework.security.authentication.AbstractAuthenticationToken; 22 | import org.springframework.security.core.Authentication; 23 | import org.springframework.security.oauth2.core.OAuth2Token; 24 | import org.springframework.security.oauth2.core.Version; 25 | import org.springframework.util.Assert; 26 | 27 | /** 28 | * An {@link Authentication} implementation used for OAuth 2.0 Token Revocation. 29 | * 30 | * @author Vivek Babu 31 | * @author Joe Grandja 32 | * @since 0.0.3 33 | * @see AbstractAuthenticationToken 34 | * @see OAuth2TokenRevocationAuthenticationProvider 35 | */ 36 | public class OAuth2TokenRevocationAuthenticationToken extends AbstractAuthenticationToken { 37 | private static final long serialVersionUID = Version.SERIAL_VERSION_UID; 38 | private final String token; 39 | private final Authentication clientPrincipal; 40 | private final String tokenTypeHint; 41 | 42 | /** 43 | * Constructs an {@code OAuth2TokenRevocationAuthenticationToken} using the provided parameters. 44 | * 45 | * @param token the token 46 | * @param clientPrincipal the authenticated client principal 47 | * @param tokenTypeHint the token type hint 48 | */ 49 | public OAuth2TokenRevocationAuthenticationToken(String token, 50 | Authentication clientPrincipal, @Nullable String tokenTypeHint) { 51 | super(Collections.emptyList()); 52 | Assert.hasText(token, "token cannot be empty"); 53 | Assert.notNull(clientPrincipal, "clientPrincipal cannot be null"); 54 | this.token = token; 55 | this.clientPrincipal = clientPrincipal; 56 | this.tokenTypeHint = tokenTypeHint; 57 | } 58 | 59 | /** 60 | * Constructs an {@code OAuth2TokenRevocationAuthenticationToken} using the provided parameters. 61 | * 62 | * @param revokedToken the revoked token 63 | * @param clientPrincipal the authenticated client principal 64 | */ 65 | public OAuth2TokenRevocationAuthenticationToken(OAuth2Token revokedToken, 66 | Authentication clientPrincipal) { 67 | super(Collections.emptyList()); 68 | Assert.notNull(revokedToken, "revokedToken cannot be null"); 69 | Assert.notNull(clientPrincipal, "clientPrincipal cannot be null"); 70 | this.token = revokedToken.getTokenValue(); 71 | this.clientPrincipal = clientPrincipal; 72 | this.tokenTypeHint = null; 73 | setAuthenticated(true); // Indicates that the token was authenticated and revoked 74 | } 75 | 76 | @Override 77 | public Object getPrincipal() { 78 | return this.clientPrincipal; 79 | } 80 | 81 | @Override 82 | public Object getCredentials() { 83 | return ""; 84 | } 85 | 86 | /** 87 | * Returns the token. 88 | * 89 | * @return the token 90 | */ 91 | public String getToken() { 92 | return this.token; 93 | } 94 | 95 | /** 96 | * Returns the token type hint. 97 | * 98 | * @return the token type hint 99 | */ 100 | @Nullable 101 | public String getTokenTypeHint() { 102 | return this.tokenTypeHint; 103 | } 104 | } 105 | --------------------------------------------------------------------------------