update spring oauth
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry including="**/*.java" kind="src" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry including="**/*.java" kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>spring-security-oauth</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.common.project.facet.core.builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
|
||||
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[3.6.3.201411271034-RELEASE]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
<enableImports><![CDATA[true]]></enableImports>
|
||||
<configs>
|
||||
</configs>
|
||||
<autoconfigs>
|
||||
</autoconfigs>
|
||||
<configSets>
|
||||
</configSets>
|
||||
</beansProjectDescription>
|
||||
@@ -0,0 +1,425 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.baeldung</groupId>
|
||||
<artifactId>spring-security-oauth</artifactId>
|
||||
<version>0.1-SNAPSHOT</version>
|
||||
|
||||
<name>spring-security-oauth</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- Spring Security -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-web</artifactId>
|
||||
<version>${org.springframework.security.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-config</artifactId>
|
||||
<version>${org.springframework.security.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.security.oauth</groupId>
|
||||
<artifactId>spring-security-oauth2</artifactId>
|
||||
<version>2.0.6.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Spring -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-jdbc</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-beans</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-aop</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-expression</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${httpclient.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${httpcore.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- persistence -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-orm</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-jpa</artifactId>
|
||||
<version>${spring-data-jpa.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-entitymanager</artifactId>
|
||||
<version>${hibernate.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>xml-apis</groupId>
|
||||
<artifactId>xml-apis</artifactId>
|
||||
<version>1.4.01</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
<version>3.18.2-GA</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
<version>${mysql-connector-java.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- web -->
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jstl</artifactId>
|
||||
<version>1.2</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- marshalling -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.4.7</version>
|
||||
</dependency>
|
||||
|
||||
<!-- util -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- logging -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
<!-- <scope>runtime</scope> -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
<!-- <scope>runtime</scope> --> <!-- some spring dependencies need to compile against jcl -->
|
||||
</dependency>
|
||||
<dependency> <!-- needed to bridge to slf4j for projects that use the log4j APIs directly -->
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>log4j-over-slf4j</artifactId>
|
||||
<version>${org.slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- test scoped -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${org.springframework.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit-dep</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-core</artifactId>
|
||||
<version>${org.hamcrest.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hamcrest</groupId>
|
||||
<artifactId>hamcrest-library</artifactId>
|
||||
<version>${org.hamcrest.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.jayway.restassured</groupId>
|
||||
<artifactId>rest-assured</artifactId>
|
||||
<version>2.3.0</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>commons-logging</artifactId>
|
||||
<groupId>commons-logging</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>spring-security-oauth</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>1.7</source>
|
||||
<target>1.7</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>${maven-war-plugin.version}</version>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>**/*IntegrationTest.java</exclude>
|
||||
<exclude>**/*LiveTest.java</exclude>
|
||||
</excludes>
|
||||
<systemPropertyVariables>
|
||||
<!-- <provPersistenceTarget>h2</provPersistenceTarget> -->
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>${cargo-maven2-plugin.version}</version>
|
||||
<configuration>
|
||||
<wait>true</wait>
|
||||
<container>
|
||||
<containerId>jetty8x</containerId>
|
||||
<type>embedded</type>
|
||||
<systemProperties>
|
||||
<!-- <provPersistenceTarget>cargo</provPersistenceTarget> -->
|
||||
</systemProperties>
|
||||
</container>
|
||||
<configuration>
|
||||
<properties>
|
||||
<cargo.servlet.port>8080</cargo.servlet.port>
|
||||
</properties>
|
||||
</configuration>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>integration</id>
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>none</exclude>
|
||||
</excludes>
|
||||
<includes>
|
||||
<include>**/*IntegrationTest.java</include>
|
||||
<include>**/*LiveTest.java</include>
|
||||
</includes>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<test.mime>json</test.mime>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<configuration>
|
||||
<wait>false</wait>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start-server</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-server</id>
|
||||
<phase>post-integration-test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<properties>
|
||||
<!-- Spring -->
|
||||
<org.springframework.version>4.1.4.RELEASE</org.springframework.version>
|
||||
<org.springframework.security.version>3.2.5.RELEASE</org.springframework.security.version>
|
||||
|
||||
<!-- persistence -->
|
||||
<hibernate.version>4.3.7.Final</hibernate.version>
|
||||
<mysql-connector-java.version>5.1.34</mysql-connector-java.version>
|
||||
<spring-data-jpa.version>1.7.1.RELEASE</spring-data-jpa.version>
|
||||
|
||||
<!-- marshalling -->
|
||||
|
||||
<jackson.version>2.4.4</jackson.version>
|
||||
|
||||
<!-- logging -->
|
||||
<org.slf4j.version>1.7.9</org.slf4j.version>
|
||||
<logback.version>1.1.2</logback.version>
|
||||
|
||||
<!-- various -->
|
||||
<hibernate-validator.version>5.1.3.Final</hibernate-validator.version>
|
||||
|
||||
<!-- util -->
|
||||
<guava.version>18.0</guava.version>
|
||||
<commons-lang3.version>3.3.2</commons-lang3.version>
|
||||
|
||||
<!-- testing -->
|
||||
<org.hamcrest.version>1.3</org.hamcrest.version>
|
||||
<junit.version>4.11</junit.version>
|
||||
<mockito.version>1.10.19</mockito.version>
|
||||
|
||||
<httpcore.version>4.4</httpcore.version>
|
||||
<httpclient.version>4.3.6</httpclient.version>
|
||||
|
||||
<rest-assured.version>2.4.0</rest-assured.version>
|
||||
|
||||
<!-- Maven plugins -->
|
||||
<maven-compiler-plugin.version>3.2</maven-compiler-plugin.version>
|
||||
<maven-war-plugin.version>2.5</maven-war-plugin.version>
|
||||
<maven-surefire-plugin.version>2.18.1</maven-surefire-plugin.version>
|
||||
<cargo-maven2-plugin.version>1.4.11</cargo-maven2-plugin.version>
|
||||
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
package org.baeldung.config;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.AnonymousAuthenticationToken;
|
||||
import org.springframework.security.authentication.InsufficientAuthenticationException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
|
||||
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
|
||||
import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
|
||||
import org.springframework.security.oauth2.client.token.AccessTokenProvider;
|
||||
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
|
||||
import org.springframework.security.oauth2.client.token.ClientTokenServices;
|
||||
import org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
|
||||
|
||||
public class MyAccessTokenProviderChain extends OAuth2AccessTokenSupport implements AccessTokenProvider {
|
||||
|
||||
private final List<AccessTokenProvider> chain;
|
||||
|
||||
private ClientTokenServices clientTokenServices;
|
||||
|
||||
public MyAccessTokenProviderChain(List<? extends AccessTokenProvider> chain) {
|
||||
this.chain = chain == null ? Collections.<AccessTokenProvider> emptyList() : Collections.unmodifiableList(chain);
|
||||
}
|
||||
|
||||
public void setClientTokenServices(ClientTokenServices clientTokenServices) {
|
||||
this.clientTokenServices = clientTokenServices;
|
||||
}
|
||||
|
||||
public boolean supportsResource(OAuth2ProtectedResourceDetails resource) {
|
||||
for (AccessTokenProvider tokenProvider : chain) {
|
||||
if (tokenProvider.supportsResource(resource)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource) {
|
||||
for (AccessTokenProvider tokenProvider : chain) {
|
||||
if (tokenProvider.supportsRefresh(resource)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails resource, AccessTokenRequest request) throws UserRedirectRequiredException, AccessDeniedException {
|
||||
System.out.println("Obtain new token=====");
|
||||
OAuth2AccessToken accessToken = null;
|
||||
OAuth2AccessToken existingToken = null;
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
System.out.println("The authentication is ---- " + auth);
|
||||
if (auth instanceof AnonymousAuthenticationToken) {
|
||||
if (!resource.isClientOnly()) {
|
||||
throw new InsufficientAuthenticationException("Authentication is required to obtain an access token (anonymous not allowed)");
|
||||
}
|
||||
}
|
||||
|
||||
if (resource.isClientOnly() || (auth != null && auth.isAuthenticated())) {
|
||||
existingToken = request.getExistingToken();
|
||||
System.out.println("checking existing token =====");
|
||||
if (existingToken == null && clientTokenServices != null) {
|
||||
System.out.println("get existing token from clientTokenServices ==== ");
|
||||
existingToken = clientTokenServices.getAccessToken(resource, auth);
|
||||
}
|
||||
|
||||
if (existingToken != null) {
|
||||
if (existingToken.isExpired()) {
|
||||
System.out.println("expired token");
|
||||
if (clientTokenServices != null) {
|
||||
clientTokenServices.removeAccessToken(resource, auth);
|
||||
}
|
||||
OAuth2RefreshToken refreshToken = existingToken.getRefreshToken();
|
||||
if (refreshToken != null) {
|
||||
System.out.println("let's refresh it");
|
||||
accessToken = refreshAccessToken(resource, refreshToken, request);
|
||||
}
|
||||
} else {
|
||||
System.out.println("use existing because not expired yet");
|
||||
accessToken = existingToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (accessToken == null) {
|
||||
System.out.println("no token so let get it");
|
||||
accessToken = obtainNewAccessTokenInternal(resource, request);
|
||||
|
||||
if (accessToken == null) {
|
||||
throw new IllegalStateException("An OAuth 2 access token must be obtained or an exception thrown.");
|
||||
}
|
||||
}
|
||||
|
||||
if (clientTokenServices != null && auth != null && auth.isAuthenticated()) {
|
||||
clientTokenServices.saveAccessToken(resource, auth, accessToken);
|
||||
}
|
||||
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
protected OAuth2AccessToken obtainNewAccessTokenInternal(OAuth2ProtectedResourceDetails details, AccessTokenRequest request) throws UserRedirectRequiredException, AccessDeniedException {
|
||||
|
||||
if (request.isError()) {
|
||||
throw OAuth2Exception.valueOf(request.toSingleValueMap());
|
||||
}
|
||||
|
||||
for (AccessTokenProvider tokenProvider : chain) {
|
||||
if (tokenProvider.supportsResource(details)) {
|
||||
System.out.println("we will use this provider to get it => " + tokenProvider.getClass().getName());
|
||||
return tokenProvider.obtainAccessToken(details, request);
|
||||
}
|
||||
}
|
||||
|
||||
throw new OAuth2AccessDeniedException("Unable to obtain a new access token for resource '" + details.getId() + "'. The provider manager is not configured to support it.", details);
|
||||
}
|
||||
|
||||
public OAuth2AccessToken refreshAccessToken(OAuth2ProtectedResourceDetails resource, OAuth2RefreshToken refreshToken, AccessTokenRequest request) throws UserRedirectRequiredException {
|
||||
for (AccessTokenProvider tokenProvider : chain) {
|
||||
if (tokenProvider.supportsRefresh(resource)) {
|
||||
System.out.println("we will use this provider to refresh it => " + tokenProvider.getClass().getName());
|
||||
return tokenProvider.refreshAccessToken(resource, refreshToken, request);
|
||||
}
|
||||
}
|
||||
throw new OAuth2AccessDeniedException("Unable to obtain a new access token for resource '" + resource.getId() + "'. The provider manager is not configured to support it.", resource);
|
||||
}
|
||||
|
||||
}
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
package org.baeldung.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.oauth2.client.filter.state.DefaultStateKeyGenerator;
|
||||
import org.springframework.security.oauth2.client.filter.state.StateKeyGenerator;
|
||||
import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException;
|
||||
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
|
||||
import org.springframework.security.oauth2.client.resource.UserApprovalRequiredException;
|
||||
import org.springframework.security.oauth2.client.resource.UserRedirectRequiredException;
|
||||
import org.springframework.security.oauth2.client.token.AccessTokenProvider;
|
||||
import org.springframework.security.oauth2.client.token.AccessTokenRequest;
|
||||
import org.springframework.security.oauth2.client.token.DefaultRequestEnhancer;
|
||||
import org.springframework.security.oauth2.client.token.RequestEnhancer;
|
||||
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider;
|
||||
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
|
||||
import org.springframework.security.oauth2.common.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
|
||||
import org.springframework.security.oauth2.common.exceptions.InvalidRequestException;
|
||||
import org.springframework.security.oauth2.common.util.OAuth2Utils;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.ResponseExtractor;
|
||||
|
||||
public class MyAuthorizationCodeAccessTokenProvider extends AuthorizationCodeAccessTokenProvider implements AccessTokenProvider {
|
||||
|
||||
private StateKeyGenerator stateKeyGenerator = new DefaultStateKeyGenerator();
|
||||
|
||||
private String scopePrefix = OAuth2Utils.SCOPE_PREFIX;
|
||||
|
||||
private RequestEnhancer authorizationRequestEnhancer = new DefaultRequestEnhancer();
|
||||
|
||||
@Override
|
||||
public void setAuthorizationRequestEnhancer(RequestEnhancer authorizationRequestEnhancer) {
|
||||
this.authorizationRequestEnhancer = authorizationRequestEnhancer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScopePrefix(String scopePrefix) {
|
||||
this.scopePrefix = scopePrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStateKeyGenerator(StateKeyGenerator stateKeyGenerator) {
|
||||
this.stateKeyGenerator = stateKeyGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsResource(OAuth2ProtectedResourceDetails resource) {
|
||||
return resource instanceof AuthorizationCodeResourceDetails && "authorization_code".equals(resource.getGrantType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRefresh(OAuth2ProtectedResourceDetails resource) {
|
||||
return supportsResource(resource);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String obtainAuthorizationCode(OAuth2ProtectedResourceDetails details, AccessTokenRequest request) throws UserRedirectRequiredException, UserApprovalRequiredException, AccessDeniedException, OAuth2AccessDeniedException {
|
||||
|
||||
AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) details;
|
||||
|
||||
HttpHeaders headers = getHeadersForAuthorizationRequest(request);
|
||||
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
|
||||
if (request.containsKey(OAuth2Utils.USER_OAUTH_APPROVAL)) {
|
||||
form.set(OAuth2Utils.USER_OAUTH_APPROVAL, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL));
|
||||
for (String scope : details.getScope()) {
|
||||
form.set(scopePrefix + scope, request.getFirst(OAuth2Utils.USER_OAUTH_APPROVAL));
|
||||
}
|
||||
} else {
|
||||
form.putAll(getParametersForAuthorizeRequest(resource, request));
|
||||
}
|
||||
form.set("duration", "permanent");
|
||||
authorizationRequestEnhancer.enhance(request, resource, form, headers);
|
||||
final AccessTokenRequest copy = request;
|
||||
|
||||
final ResponseExtractor<ResponseEntity<Void>> delegate = getAuthorizationResponseExtractor();
|
||||
ResponseExtractor<ResponseEntity<Void>> extractor = new ResponseExtractor<ResponseEntity<Void>>() {
|
||||
@Override
|
||||
public ResponseEntity<Void> extractData(ClientHttpResponse response) throws IOException {
|
||||
if (response.getHeaders().containsKey("Set-Cookie")) {
|
||||
copy.setCookie(response.getHeaders().getFirst("Set-Cookie"));
|
||||
}
|
||||
return delegate.extractData(response);
|
||||
}
|
||||
};
|
||||
|
||||
ResponseEntity<Void> response = getRestTemplate().execute(resource.getUserAuthorizationUri(), HttpMethod.POST, getRequestCallback(resource, form, headers), extractor, form.toSingleValueMap());
|
||||
|
||||
if (response.getStatusCode() == HttpStatus.OK) {
|
||||
throw getUserApprovalSignal(resource, request);
|
||||
}
|
||||
|
||||
URI location = response.getHeaders().getLocation();
|
||||
String query = location.getQuery();
|
||||
Map<String, String> map = OAuth2Utils.extractMap(query);
|
||||
if (map.containsKey("state")) {
|
||||
request.setStateKey(map.get("state"));
|
||||
if (request.getPreservedState() == null) {
|
||||
String redirectUri = resource.getRedirectUri(request);
|
||||
if (redirectUri != null) {
|
||||
request.setPreservedState(redirectUri);
|
||||
} else {
|
||||
request.setPreservedState(new Object());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String code = map.get("code");
|
||||
if (code == null) {
|
||||
throw new UserRedirectRequiredException(location.toString(), form.toSingleValueMap());
|
||||
}
|
||||
request.set("code", code);
|
||||
return code;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResponseExtractor<ResponseEntity<Void>> getAuthorizationResponseExtractor() {
|
||||
return new ResponseExtractor<ResponseEntity<Void>>() {
|
||||
public ResponseEntity<Void> extractData(ClientHttpResponse response) throws IOException {
|
||||
return new ResponseEntity<Void>(response.getHeaders(), response.getStatusCode());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken obtainAccessToken(OAuth2ProtectedResourceDetails details, AccessTokenRequest request) throws UserRedirectRequiredException, UserApprovalRequiredException, AccessDeniedException, OAuth2AccessDeniedException {
|
||||
|
||||
AuthorizationCodeResourceDetails resource = (AuthorizationCodeResourceDetails) details;
|
||||
|
||||
if (request.getAuthorizationCode() == null) {
|
||||
if (request.getStateKey() == null) {
|
||||
throw getRedirectForAuthorization(resource, request);
|
||||
}
|
||||
obtainAuthorizationCode(resource, request);
|
||||
}
|
||||
return retrieveToken(request, resource, getParametersForTokenRequest(resource, request), getHeadersForTokenRequest(request));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public OAuth2AccessToken refreshAccessToken(OAuth2ProtectedResourceDetails resource, OAuth2RefreshToken refreshToken, AccessTokenRequest request) throws UserRedirectRequiredException, OAuth2AccessDeniedException {
|
||||
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
|
||||
form.add("grant_type", "refresh_token");
|
||||
form.add("refresh_token", refreshToken.getValue());
|
||||
try {
|
||||
return retrieveToken(request, resource, form, getHeadersForTokenRequest(request));
|
||||
} catch (OAuth2AccessDeniedException e) {
|
||||
throw getRedirectForAuthorization((AuthorizationCodeResourceDetails) resource, request);
|
||||
}
|
||||
}
|
||||
|
||||
private HttpHeaders getHeadersForTokenRequest(AccessTokenRequest request) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
// No cookie for token request
|
||||
return headers;
|
||||
}
|
||||
|
||||
private HttpHeaders getHeadersForAuthorizationRequest(AccessTokenRequest request) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.putAll(request.getHeaders());
|
||||
if (request.getCookie() != null) {
|
||||
headers.set("Cookie", request.getCookie());
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
private MultiValueMap<String, String> getParametersForTokenRequest(AuthorizationCodeResourceDetails resource, AccessTokenRequest request) {
|
||||
|
||||
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
|
||||
form.set("grant_type", "authorization_code");
|
||||
form.set("code", request.getAuthorizationCode());
|
||||
|
||||
Object preservedState = request.getPreservedState();
|
||||
if (request.getStateKey() != null) {
|
||||
if (preservedState == null) {
|
||||
throw new InvalidRequestException("Possible CSRF detected - state parameter was present but no state could be found");
|
||||
}
|
||||
}
|
||||
|
||||
String redirectUri = null;
|
||||
if (preservedState instanceof String) {
|
||||
redirectUri = String.valueOf(preservedState);
|
||||
} else {
|
||||
redirectUri = resource.getRedirectUri(request);
|
||||
}
|
||||
|
||||
if (redirectUri != null && !"NONE".equals(redirectUri)) {
|
||||
form.set("redirect_uri", redirectUri);
|
||||
}
|
||||
|
||||
return form;
|
||||
|
||||
}
|
||||
|
||||
private MultiValueMap<String, String> getParametersForAuthorizeRequest(AuthorizationCodeResourceDetails resource, AccessTokenRequest request) {
|
||||
|
||||
MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>();
|
||||
form.set("response_type", "code");
|
||||
form.set("client_id", resource.getClientId());
|
||||
|
||||
if (request.get("scope") != null) {
|
||||
form.set("scope", request.getFirst("scope"));
|
||||
} else {
|
||||
form.set("scope", OAuth2Utils.formatParameterList(resource.getScope()));
|
||||
}
|
||||
|
||||
String redirectUri = resource.getPreEstablishedRedirectUri();
|
||||
|
||||
Object preservedState = request.getPreservedState();
|
||||
if (redirectUri == null && preservedState != null) {
|
||||
redirectUri = String.valueOf(preservedState);
|
||||
} else {
|
||||
redirectUri = request.getCurrentUri();
|
||||
}
|
||||
|
||||
String stateKey = request.getStateKey();
|
||||
if (stateKey != null) {
|
||||
form.set("state", stateKey);
|
||||
if (preservedState == null) {
|
||||
throw new InvalidRequestException("Possible CSRF detected - state parameter was present but no state could be found");
|
||||
}
|
||||
}
|
||||
|
||||
if (redirectUri != null) {
|
||||
form.set("redirect_uri", redirectUri);
|
||||
}
|
||||
|
||||
return form;
|
||||
|
||||
}
|
||||
|
||||
private UserRedirectRequiredException getRedirectForAuthorization(AuthorizationCodeResourceDetails resource, AccessTokenRequest request) {
|
||||
|
||||
// we don't have an authorization code yet. So first get that.
|
||||
TreeMap<String, String> requestParameters = new TreeMap<String, String>();
|
||||
requestParameters.put("response_type", "code"); // oauth2 spec, section 3
|
||||
requestParameters.put("client_id", resource.getClientId());
|
||||
requestParameters.put("duration", "permanent");
|
||||
// Client secret is not required in the initial authorization request
|
||||
|
||||
String redirectUri = resource.getRedirectUri(request);
|
||||
if (redirectUri != null) {
|
||||
requestParameters.put("redirect_uri", redirectUri);
|
||||
}
|
||||
|
||||
if (resource.isScoped()) {
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
List<String> scope = resource.getScope();
|
||||
|
||||
if (scope != null) {
|
||||
Iterator<String> scopeIt = scope.iterator();
|
||||
while (scopeIt.hasNext()) {
|
||||
builder.append(scopeIt.next());
|
||||
if (scopeIt.hasNext()) {
|
||||
builder.append(' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requestParameters.put("scope", builder.toString());
|
||||
}
|
||||
|
||||
UserRedirectRequiredException redirectException = new UserRedirectRequiredException(resource.getUserAuthorizationUri(), requestParameters);
|
||||
|
||||
String stateKey = stateKeyGenerator.generateKey(resource);
|
||||
redirectException.setStateKey(stateKey);
|
||||
request.setStateKey(stateKey);
|
||||
redirectException.setStateToPreserve(redirectUri);
|
||||
request.setPreservedState(redirectUri);
|
||||
|
||||
return redirectException;
|
||||
|
||||
}
|
||||
|
||||
protected UserApprovalRequiredException getUserApprovalSignal(AuthorizationCodeResourceDetails resource, AccessTokenRequest request) {
|
||||
String message = String.format("Do you approve the client '%s' to access your resources with scope=%s", resource.getClientId(), resource.getScope());
|
||||
return new UserApprovalRequiredException(resource.getUserAuthorizationUri(), Collections.singletonMap(OAuth2Utils.USER_OAUTH_APPROVAL, message), resource.getClientId(), resource.getScope());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package org.baeldung.config;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
|
||||
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
|
||||
import org.springframework.jdbc.datasource.DriverManagerDataSource;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
|
||||
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@PropertySource({ "classpath:persistence.properties" })
|
||||
@ComponentScan({ "org.baeldung.persistence" })
|
||||
@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao")
|
||||
public class PersistenceJPAConfig {
|
||||
|
||||
@Autowired
|
||||
private Environment env;
|
||||
|
||||
public PersistenceJPAConfig() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
|
||||
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
|
||||
em.setDataSource(dataSource());
|
||||
em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" });
|
||||
final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
|
||||
em.setJpaVendorAdapter(vendorAdapter);
|
||||
em.setJpaProperties(additionalProperties());
|
||||
return em;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DataSource dataSource() {
|
||||
final DriverManagerDataSource dataSource = new DriverManagerDataSource();
|
||||
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
|
||||
dataSource.setUrl(env.getProperty("jdbc.url"));
|
||||
dataSource.setUsername(env.getProperty("jdbc.user"));
|
||||
dataSource.setPassword(env.getProperty("jdbc.pass"));
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JpaTransactionManager transactionManager() {
|
||||
final JpaTransactionManager transactionManager = new JpaTransactionManager();
|
||||
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
|
||||
return transactionManager;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
|
||||
return new PersistenceExceptionTranslationPostProcessor();
|
||||
}
|
||||
|
||||
final Properties additionalProperties() {
|
||||
final Properties hibernateProperties = new Properties();
|
||||
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto"));
|
||||
hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect"));
|
||||
return hibernateProperties;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.baeldung.config;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
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.UserDetailsService;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@ComponentScan(basePackages = { "org.baeldung.security" })
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
@Bean
|
||||
public DaoAuthenticationProvider authProvider() {
|
||||
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
|
||||
authProvider.setUserDetailsService(userDetailsService);
|
||||
return authProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.authenticationProvider(authProvider());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring().antMatchers("/resources/**");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http.anonymous().disable().authorizeRequests()
|
||||
.antMatchers("/**").permitAll()
|
||||
.antMatchers("/reddit","/reddit/**").hasRole("User");
|
||||
// .and()
|
||||
// .formLogin()
|
||||
// .loginPage("/login")
|
||||
// .permitAll();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.baeldung.config;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
|
||||
import org.springframework.web.filter.DelegatingFilterProxy;
|
||||
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
|
||||
|
||||
public class ServletInitializer extends AbstractDispatcherServletInitializer {
|
||||
|
||||
@Override
|
||||
protected WebApplicationContext createServletApplicationContext() {
|
||||
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
|
||||
context.register(PersistenceJPAConfig.class, SecurityConfig.class, WebConfig.class);
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getServletMappings() {
|
||||
return new String[] { "/" };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WebApplicationContext createRootApplicationContext() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
super.onStartup(servletContext);
|
||||
registerProxyFilter(servletContext, "oauth2ClientContextFilter");
|
||||
// registerProxyFilter(servletContext, "springSecurityFilterChain");
|
||||
}
|
||||
|
||||
private void registerProxyFilter(ServletContext servletContext, String name) {
|
||||
DelegatingFilterProxy filter = new DelegatingFilterProxy(name);
|
||||
filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");
|
||||
servletContext.addFilter(name, filter).addMappingForUrlPatterns(null, false, "/*");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.baeldung.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.baeldung.web.RedditController;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
|
||||
import org.springframework.security.oauth2.client.OAuth2ClientContext;
|
||||
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
|
||||
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
|
||||
import org.springframework.security.oauth2.client.token.AccessTokenProvider;
|
||||
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsAccessTokenProvider;
|
||||
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
|
||||
import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitAccessTokenProvider;
|
||||
import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordAccessTokenProvider;
|
||||
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
|
||||
import org.springframework.web.servlet.ViewResolver;
|
||||
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
|
||||
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
|
||||
import org.springframework.web.servlet.view.InternalResourceViewResolver;
|
||||
|
||||
@Configuration
|
||||
@EnableWebMvc
|
||||
public class WebConfig extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Bean
|
||||
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
|
||||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewResolver viewResolver() {
|
||||
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
|
||||
viewResolver.setPrefix("/WEB-INF/jsp/");
|
||||
viewResolver.setSuffix(".jsp");
|
||||
return viewResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
|
||||
configurer.enable();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RedditController redditController(@Qualifier("redditRestTemplate") OAuth2RestTemplate redditRestTemplate) {
|
||||
RedditController controller = new RedditController();
|
||||
controller.setRedditRestTemplate(redditRestTemplate);
|
||||
return controller;
|
||||
}
|
||||
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableOAuth2Client
|
||||
@PropertySource("classpath:reddit.properties")
|
||||
protected static class ResourceConfiguration {
|
||||
|
||||
@Value("${accessTokenUri}")
|
||||
private String accessTokenUri;
|
||||
|
||||
@Value("${userAuthorizationUri}")
|
||||
private String userAuthorizationUri;
|
||||
|
||||
@Value("${clientID}")
|
||||
private String clientID;
|
||||
|
||||
@Value("${clientSecret}")
|
||||
private String clientSecret;
|
||||
|
||||
@Bean
|
||||
public OAuth2ProtectedResourceDetails reddit() {
|
||||
AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
|
||||
details.setId("reddit");
|
||||
details.setClientId(clientID);
|
||||
details.setClientSecret(clientSecret);
|
||||
details.setAccessTokenUri(accessTokenUri);
|
||||
details.setUserAuthorizationUri(userAuthorizationUri);
|
||||
details.setTokenName("oauth_token");
|
||||
details.setScope(Arrays.asList("identity"));
|
||||
details.setGrantType("authorization_code");
|
||||
return details;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2RestTemplate redditRestTemplate(OAuth2ClientContext clientContext) {
|
||||
OAuth2RestTemplate template = new OAuth2RestTemplate(reddit(), clientContext);
|
||||
AccessTokenProvider accessTokenProvider = new MyAccessTokenProviderChain(Arrays.<AccessTokenProvider> asList(new MyAuthorizationCodeAccessTokenProvider(), new ImplicitAccessTokenProvider(), new ResourceOwnerPasswordAccessTokenProvider(),
|
||||
new ClientCredentialsAccessTokenProvider()));
|
||||
template.setAccessTokenProvider(accessTokenProvider);
|
||||
return template;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.baeldung.persistence.dao;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface UserRepository extends JpaRepository<User, Long> {
|
||||
public User findByUsername(String name);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.baeldung.persistence.model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
|
||||
@Entity
|
||||
public class User {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
||||
private String username;
|
||||
|
||||
private String password;
|
||||
|
||||
public User() {
|
||||
super();
|
||||
}
|
||||
|
||||
public User(String username, String password) {
|
||||
super();
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.baeldung.security;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.baeldung.persistence.dao.UserRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service("userDetailsService")
|
||||
@Transactional
|
||||
public class MyUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
public MyUserDetailsService() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(final String name) {
|
||||
org.baeldung.persistence.model.User user = userRepository.findByUsername(name);
|
||||
if (user == null) {
|
||||
user = new org.baeldung.persistence.model.User(name, UUID.randomUUID().toString());
|
||||
user = userRepository.save(user);
|
||||
}
|
||||
return new User(user.getUsername(), user.getPassword(), getGrantedAuthorities(Arrays.asList("ROLE_USER")));
|
||||
}
|
||||
|
||||
private static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
|
||||
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
|
||||
for (String role : roles) {
|
||||
authorities.add(new SimpleGrantedAuthority(role));
|
||||
}
|
||||
return authorities;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.baeldung.web;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
@Controller
|
||||
public class RedditController {
|
||||
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
private OAuth2RestTemplate redditRestTemplate;
|
||||
|
||||
@RequestMapping("/info")
|
||||
public String getInfo(Model model) throws Exception {
|
||||
String result = redditRestTemplate.getForObject("https://oauth.reddit.com/api/v1/me", String.class);
|
||||
JsonNode node = new ObjectMapper().readTree(result);
|
||||
String name = node.get("name").asText();
|
||||
model.addAttribute("info", name);
|
||||
|
||||
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
|
||||
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, userDetails.getPassword(), userDetails.getAuthorities());
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
return "reddit";
|
||||
}
|
||||
|
||||
@RequestMapping("/reddit/test")
|
||||
public String test(Model model) {
|
||||
return "test";
|
||||
}
|
||||
|
||||
public void setRedditRestTemplate(OAuth2RestTemplate redditRestTemplate) {
|
||||
this.redditRestTemplate = redditRestTemplate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<!-- Appenders -->
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- Application Loggers -->
|
||||
<logger name="org.baeldung.web">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<!-- 3rdparty Loggers -->
|
||||
<logger name="org.springframework.core">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.beans">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.context">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.web">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="warn" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
@@ -0,0 +1,10 @@
|
||||
################### DataSource Configuration ##########################
|
||||
jdbc.driverClassName=com.mysql.jdbc.Driver
|
||||
jdbc.url=jdbc:mysql://localhost:3606/oauth?createDatabaseIfNotExist=true
|
||||
jdbc.user=tutorialuser
|
||||
jdbc.pass=tutorialmy5ql
|
||||
init-db=false
|
||||
################### Hibernate Configuration ##########################
|
||||
hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
||||
hibernate.show_sql=false
|
||||
hibernate.hbm2ddl.auto=create-drop
|
||||
@@ -0,0 +1,4 @@
|
||||
clientID=5iAHD5-BBmEL8Q
|
||||
clientSecret=grkII6-THVcFsMm1wVTiQDRONmw
|
||||
accessTokenUri=https://www.reddit.com/api/v1/access_token
|
||||
userAuthorizationUri=https://www.reddit.com/api/v1/authorize
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
|
||||
<title>Spring Security OAuth</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Your Reddit Info</h1>
|
||||
<b>Your reddit username is </b>${info}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
|
||||
<title>Spring Security OAuth</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Test</h1>
|
||||
<b>Test </b>
|
||||
</body>
|
||||
</html>
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>Spring Security OAuth</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>Welcome to Spring Security OAuth</h1>
|
||||
<a href="info">Login with Reddit</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "log4j.dtd">
|
||||
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
|
||||
|
||||
<!-- Appenders -->
|
||||
<appender name="console" class="org.apache.log4j.ConsoleAppender">
|
||||
<param name="Target" value="System.out" />
|
||||
<layout class="org.apache.log4j.PatternLayout">
|
||||
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<!-- Application Loggers -->
|
||||
<logger name="org.baeldung.web">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<!-- 3rdparty Loggers -->
|
||||
<logger name="org.springframework.core">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.beans">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.context">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.web">
|
||||
<level value="info" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="info" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
</log4j:configuration>
|
||||
Reference in New Issue
Block a user