19 changed files with 704 additions and 0 deletions
@ -0,0 +1,11 @@
@@ -0,0 +1,11 @@
|
||||
= OAuth 2.0 Integration Sample |
||||
|
||||
This sample integrates `spring-security-oauth2-client` and `spring-security-oauth2-resource-server` with *Spring Authorization Server*. |
||||
|
||||
== Run the Sample |
||||
|
||||
* Run Authorization Server -> `./gradlew -b samples/boot/oauth2-integration/authorizationserver/spring-security-samples-boot-oauth2-integrated-authorizationserver.gradle bootRun` |
||||
** *IMPORTANT:* Make sure to modify your `/etc/hosts` file to avoid problems with session cookie overwrites between `client` and `authorizationserver`. Simply add the entry `127.0.0.1 auth-server` |
||||
* Run Resource Server -> `./gradlew -b samples/boot/oauth2-integration/resourceserver/spring-security-samples-boot-oauth2-integrated-resourceserver.gradle bootRun` |
||||
* Run Client -> `./gradlew -b samples/boot/oauth2-integration/client/spring-security-samples-boot-oauth2-integrated-client.gradle bootRun` |
||||
* Go to `http://localhost:8080` and login using *user1/password* |
||||
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
apply plugin: 'io.spring.convention.spring-sample-boot' |
||||
|
||||
dependencies { |
||||
compile 'org.springframework.boot:spring-boot-starter-web' |
||||
compile 'org.springframework.boot:spring-boot-starter-security' |
||||
compile project(':spring-security-oauth2-authorization-server') |
||||
compile project(':spring-security-config2') |
||||
compile project(':spring-security-crypto2') |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@SpringBootApplication |
||||
public class OAuth2AuthorizationServerApplication { |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(OAuth2AuthorizationServerApplication.class, args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,77 @@
@@ -0,0 +1,77 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.config; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Import; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration; |
||||
import org.springframework.security.core.userdetails.User; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
import org.springframework.security.core.userdetails.UserDetailsService; |
||||
import org.springframework.security.crypto.keys.KeyManager; |
||||
import org.springframework.security.crypto.keys.StaticKeyGeneratingKeyManager; |
||||
import org.springframework.security.oauth2.core.AuthorizationGrantType; |
||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod; |
||||
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository; |
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; |
||||
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; |
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@EnableWebSecurity |
||||
@Import(OAuth2AuthorizationServerConfiguration.class) |
||||
public class AuthorizationServerConfig { |
||||
|
||||
// @formatter:off
|
||||
@Bean |
||||
public RegisteredClientRepository registeredClientRepository() { |
||||
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString()) |
||||
.clientId("messaging-client") |
||||
.clientSecret("secret") |
||||
.clientAuthenticationMethod(ClientAuthenticationMethod.BASIC) |
||||
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) |
||||
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS) |
||||
.redirectUri("http://localhost:8080/authorized") |
||||
.scope("message.read") |
||||
.scope("message.write") |
||||
.build(); |
||||
return new InMemoryRegisteredClientRepository(registeredClient); |
||||
} |
||||
// @formatter:on
|
||||
|
||||
@Bean |
||||
public KeyManager keyManager() { |
||||
return new StaticKeyGeneratingKeyManager(); |
||||
} |
||||
|
||||
// @formatter:off
|
||||
@Bean |
||||
public UserDetailsService users() { |
||||
UserDetails user = User.withDefaultPasswordEncoder() |
||||
.username("user1") |
||||
.password("password") |
||||
.roles("USER") |
||||
.build(); |
||||
return new InMemoryUserDetailsManager(user); |
||||
} |
||||
// @formatter:on
|
||||
} |
||||
@ -0,0 +1,10 @@
@@ -0,0 +1,10 @@
|
||||
server: |
||||
port: 9000 |
||||
|
||||
logging: |
||||
level: |
||||
root: INFO |
||||
org.springframework.web: INFO |
||||
org.springframework.security: INFO |
||||
org.springframework.security.oauth2: INFO |
||||
# org.springframework.boot.autoconfigure: DEBUG |
||||
@ -0,0 +1,14 @@
@@ -0,0 +1,14 @@
|
||||
apply plugin: 'io.spring.convention.spring-sample-boot' |
||||
|
||||
dependencies { |
||||
compile 'org.springframework.boot:spring-boot-starter-web' |
||||
compile 'org.springframework.boot:spring-boot-starter-thymeleaf' |
||||
compile 'org.springframework.boot:spring-boot-starter-security' |
||||
compile 'org.springframework.boot:spring-boot-starter-oauth2-client' |
||||
compile 'org.springframework:spring-webflux' |
||||
compile 'io.projectreactor.netty:reactor-netty' |
||||
compile 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5' |
||||
compile 'org.webjars:webjars-locator-core' |
||||
compile 'org.webjars:bootstrap:3.4.1' |
||||
compile 'org.webjars:jquery:3.4.1' |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@SpringBootApplication |
||||
public class OAuth2ClientApplication { |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(OAuth2ClientApplication.class, args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.config; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
||||
import org.springframework.security.core.userdetails.User; |
||||
import org.springframework.security.core.userdetails.UserDetails; |
||||
import org.springframework.security.core.userdetails.UserDetailsService; |
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@EnableWebSecurity |
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter { |
||||
|
||||
// @formatter:off
|
||||
@Override |
||||
public void configure(WebSecurity web) { |
||||
web |
||||
.ignoring() |
||||
.antMatchers("/webjars/**"); |
||||
} |
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@Override |
||||
protected void configure(HttpSecurity http) throws Exception { |
||||
http |
||||
.authorizeRequests() |
||||
.anyRequest().authenticated() |
||||
.and() |
||||
.formLogin() |
||||
.loginPage("/login") |
||||
.failureUrl("/login-error") |
||||
.permitAll() |
||||
.and() |
||||
.oauth2Client(); |
||||
} |
||||
// @formatter:on
|
||||
|
||||
// @formatter:off
|
||||
@Bean |
||||
public UserDetailsService users() { |
||||
UserDetails user = User.withDefaultPasswordEncoder() |
||||
.username("user1") |
||||
.password("password") |
||||
.roles("USER") |
||||
.build(); |
||||
return new InMemoryUserDetailsManager(user); |
||||
} |
||||
// @formatter:on
|
||||
} |
||||
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.config; |
||||
|
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager; |
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProvider; |
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder; |
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; |
||||
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager; |
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository; |
||||
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; |
||||
import org.springframework.web.reactive.function.client.WebClient; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@Configuration |
||||
public class WebClientConfig { |
||||
|
||||
@Bean |
||||
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { |
||||
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = |
||||
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); |
||||
return WebClient.builder() |
||||
.apply(oauth2Client.oauth2Configuration()) |
||||
.build(); |
||||
} |
||||
|
||||
@Bean |
||||
OAuth2AuthorizedClientManager authorizedClientManager( |
||||
ClientRegistrationRepository clientRegistrationRepository, |
||||
OAuth2AuthorizedClientRepository authorizedClientRepository) { |
||||
|
||||
OAuth2AuthorizedClientProvider authorizedClientProvider = |
||||
OAuth2AuthorizedClientProviderBuilder.builder() |
||||
.authorizationCode() |
||||
.clientCredentials() |
||||
.build(); |
||||
DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( |
||||
clientRegistrationRepository, authorizedClientRepository); |
||||
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); |
||||
|
||||
return authorizedClientManager; |
||||
} |
||||
} |
||||
@ -0,0 +1,75 @@
@@ -0,0 +1,75 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.web; |
||||
|
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; |
||||
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; |
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.ui.Model; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.reactive.function.client.WebClient; |
||||
|
||||
import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId; |
||||
import static org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.oauth2AuthorizedClient; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@Controller |
||||
public class AuthorizationController { |
||||
private final WebClient webClient; |
||||
private final String messagesBaseUri; |
||||
|
||||
public AuthorizationController(WebClient webClient, |
||||
@Value("${messages.base-uri}") String messagesBaseUri) { |
||||
this.webClient = webClient; |
||||
this.messagesBaseUri = messagesBaseUri; |
||||
} |
||||
|
||||
@GetMapping(value = "/authorize", params = "grant_type=authorization_code") |
||||
public String authorizationCodeGrant(Model model, |
||||
@RegisteredOAuth2AuthorizedClient("messaging-client-authorization-code") |
||||
OAuth2AuthorizedClient authorizedClient) { |
||||
|
||||
String[] messages = this.webClient |
||||
.get() |
||||
.uri(this.messagesBaseUri) |
||||
.attributes(oauth2AuthorizedClient(authorizedClient)) |
||||
.retrieve() |
||||
.bodyToMono(String[].class) |
||||
.block(); |
||||
model.addAttribute("messages", messages); |
||||
|
||||
return "index"; |
||||
} |
||||
|
||||
@GetMapping(value = "/authorize", params = "grant_type=client_credentials") |
||||
public String clientCredentialsGrant(Model model) { |
||||
|
||||
String[] messages = this.webClient |
||||
.get() |
||||
.uri(this.messagesBaseUri) |
||||
.attributes(clientRegistrationId("messaging-client-client-credentials")) |
||||
.retrieve() |
||||
.bodyToMono(String[].class) |
||||
.block(); |
||||
model.addAttribute("messages", messages); |
||||
|
||||
return "index"; |
||||
} |
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.web; |
||||
|
||||
import org.springframework.stereotype.Controller; |
||||
import org.springframework.ui.Model; |
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@Controller |
||||
public class DefaultController { |
||||
|
||||
@GetMapping("/") |
||||
public String root() { |
||||
return "redirect:/index"; |
||||
} |
||||
|
||||
@GetMapping("/index") |
||||
public String index() { |
||||
return "index"; |
||||
} |
||||
|
||||
@GetMapping("/login") |
||||
public String login() { |
||||
return "login"; |
||||
} |
||||
|
||||
@GetMapping("/login-error") |
||||
public String loginError(Model model) { |
||||
model.addAttribute("loginError", true); |
||||
return login(); |
||||
} |
||||
} |
||||
@ -0,0 +1,38 @@
@@ -0,0 +1,38 @@
|
||||
server: |
||||
port: 8080 |
||||
|
||||
logging: |
||||
level: |
||||
root: INFO |
||||
org.springframework.web: INFO |
||||
org.springframework.security: INFO |
||||
org.springframework.security.oauth2: INFO |
||||
# org.springframework.boot.autoconfigure: DEBUG |
||||
|
||||
spring: |
||||
thymeleaf: |
||||
cache: false |
||||
security: |
||||
oauth2: |
||||
client: |
||||
registration: |
||||
messaging-client-authorization-code: |
||||
provider: spring |
||||
client-id: messaging-client |
||||
client-secret: secret |
||||
authorization-grant-type: authorization_code |
||||
redirect-uri: "{baseUrl}/authorized" |
||||
scope: message.read,message.write |
||||
messaging-client-client-credentials: |
||||
provider: spring |
||||
client-id: messaging-client |
||||
client-secret: secret |
||||
authorization-grant-type: client_credentials |
||||
scope: message.read,message.write |
||||
provider: |
||||
spring: |
||||
authorization-uri: http://auth-server:9000/oauth2/authorize |
||||
token-uri: http://auth-server:9000/oauth2/token |
||||
|
||||
messages: |
||||
base-uri: http://localhost:8090/messages |
||||
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
<!DOCTYPE html> |
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org" xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5"> |
||||
<head> |
||||
<title>Spring Security OAuth 2.0 Sample</title> |
||||
<meta charset="utf-8" /> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
||||
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" /> |
||||
</head> |
||||
<body> |
||||
<div th:fragment="header"> |
||||
<nav class="navbar navbar-default"> |
||||
<div class="container"> |
||||
<div class="container-fluid"> |
||||
<div class="navbar-collapse collapse" id="navbar"> |
||||
<ul class="nav navbar-nav navbar-right"> |
||||
<li class="dropdown"> |
||||
<a id="user-menu" href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> |
||||
<span sec:authentication="name">User</span> |
||||
</a> |
||||
<ul class="dropdown-menu"> |
||||
<li><a id="sign-out" href="javascript:document.logoutForm.submit()">Sign Out</a></li> |
||||
</ul> |
||||
<form name="logoutForm" th:action="@{/logout}" method="post" th:hidden="true"> |
||||
<input hidden type="submit" value="Sign Out"/> |
||||
</form> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</nav> |
||||
</div> |
||||
<div class="container"> |
||||
<div class="panel panel-default"> |
||||
<div class="panel-heading"> |
||||
<h3 class="panel-title">Authorize the client using <span style="font-family:monospace">grant_type</span>:</h3> |
||||
</div> |
||||
<ul class="list-group"> |
||||
<li class="list-group-item"> |
||||
<a href="/authorize?grant_type=authorization_code" th:href="@{/authorize?grant_type=authorization_code}"><span style="font-size:medium">Authorization Code</span> <small class="text-muted">(Login to Spring Authorization Server using: user1/password)</small></a> |
||||
</li> |
||||
<li class="list-group-item"> |
||||
<a href="/authorize?grant_type=client_credentials" th:href="@{/authorize?grant_type=client_credentials}"><span style="font-size:medium">Client Credentials</span></a> |
||||
</li> |
||||
</ul> |
||||
<div th:if="${messages}" class="panel-footer"> |
||||
<h4>Messages:</h4> |
||||
<table class="table table-condensed"> |
||||
<tbody> |
||||
<tr class="row" th:each="message : ${messages}"> |
||||
<td th:text="${message}">message</td> |
||||
</tr> |
||||
</tbody> |
||||
</table> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script> |
||||
<script src="/webjars/bootstrap/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,34 @@
@@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html> |
||||
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org"> |
||||
<head> |
||||
<title>Spring Security OAuth 2.0 Sample</title> |
||||
<meta charset="utf-8" /> |
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
||||
<link rel="stylesheet" href="/webjars/bootstrap/css/bootstrap.css" th:href="@{/webjars/bootstrap/css/bootstrap.css}" /> |
||||
</head> |
||||
<body> |
||||
<div class="container"> |
||||
<h1>Login</h1> |
||||
<p th:if="${loginError}" style="font-weight:bold;color:red;">Wrong username or password</p> |
||||
<form th:action="@{/login}" method="post"> |
||||
<div class="form-row"> |
||||
<div class="form-group"> |
||||
<label for="username">Username</label> |
||||
<input type="text" id="username" name="username" value="user1" autofocus="autofocus" class="form-control"> |
||||
<small class="form-text text-muted">user1 / password</small> |
||||
</div> |
||||
</div> |
||||
<div class="form-row"> |
||||
<div class="form-group"> |
||||
<label for="password">Password</label> |
||||
<input type="password" id="password" name="password" value="password" class="form-control"> |
||||
</div> |
||||
</div> |
||||
<button type="submit" class="btn btn-primary">Log in</button> |
||||
</form> |
||||
</div> |
||||
<script src="/webjars/jquery/jquery.min.js" th:src="@{/webjars/jquery/jquery.min.js}"></script> |
||||
<script src="/webjars/bootstrap/js/bootstrap.min.js" th:src="@{/webjars/bootstrap/js/bootstrap.min.js}"></script> |
||||
</body> |
||||
</html> |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
apply plugin: 'io.spring.convention.spring-sample-boot' |
||||
|
||||
dependencies { |
||||
compile 'org.springframework.boot:spring-boot-starter-web' |
||||
compile 'org.springframework.boot:spring-boot-starter-security' |
||||
compile 'org.springframework.boot:spring-boot-starter-oauth2-resource-server' |
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample; |
||||
|
||||
import org.springframework.boot.SpringApplication; |
||||
import org.springframework.boot.autoconfigure.SpringBootApplication; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@SpringBootApplication |
||||
public class OAuth2ResourceServerApplication { |
||||
|
||||
public static void main(String[] args) { |
||||
SpringApplication.run(OAuth2ResourceServerApplication.class, args); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.config; |
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; |
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@EnableWebSecurity |
||||
public class ResourceServerConfig extends WebSecurityConfigurerAdapter { |
||||
|
||||
// @formatter:off
|
||||
@Override |
||||
protected void configure(HttpSecurity http) throws Exception { |
||||
http |
||||
.mvcMatcher("/messages/**") |
||||
.authorizeRequests() |
||||
.mvcMatchers("/messages/**").access("hasAuthority('SCOPE_message.read')") |
||||
.and() |
||||
.oauth2ResourceServer() |
||||
.jwt(); |
||||
} |
||||
// @formatter:on
|
||||
} |
||||
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
/* |
||||
* Copyright 2020 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package sample.web; |
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping; |
||||
import org.springframework.web.bind.annotation.RestController; |
||||
|
||||
/** |
||||
* @author Joe Grandja |
||||
* @since 0.0.1 |
||||
*/ |
||||
@RestController |
||||
public class MessagesController { |
||||
|
||||
@GetMapping("/messages") |
||||
public String[] getMessages() { |
||||
return new String[] {"Message 1", "Message 2", "Message 3"}; |
||||
} |
||||
} |
||||
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
server: |
||||
port: 8090 |
||||
|
||||
logging: |
||||
level: |
||||
root: INFO |
||||
org.springframework.web: INFO |
||||
org.springframework.security: INFO |
||||
org.springframework.security.oauth2: INFO |
||||
# org.springframework.boot.autoconfigure: DEBUG |
||||
|
||||
spring: |
||||
security: |
||||
oauth2: |
||||
resourceserver: |
||||
jwt: |
||||
jwk-set-uri: http://auth-server:9000/oauth2/jwks |
||||
Loading…
Reference in new issue