-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cccdb55
commit 049ad45
Showing
51 changed files
with
3,606 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.example.authorizationserver | ||
|
||
import com.example.authorizationserver.props.ClientSecurityProperties | ||
import com.example.authorizationserver.props.ServerProperties | ||
import com.example.authorizationserver.props.SpringDataProperties | ||
import com.example.authorizationserver.props.SpringSessionProperties | ||
import org.springframework.boot.autoconfigure.SpringBootApplication | ||
import org.springframework.boot.context.properties.EnableConfigurationProperties | ||
import org.springframework.boot.runApplication | ||
|
||
@SpringBootApplication | ||
@EnableConfigurationProperties( | ||
ServerProperties::class, | ||
ClientSecurityProperties::class, | ||
SpringDataProperties::class, | ||
SpringSessionProperties::class | ||
) | ||
internal class AuthorizationServerApplication | ||
|
||
fun main(args: Array<String>) { | ||
// run SpringBoot application | ||
runApplication<AuthorizationServerApplication>(*args) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package com.example.authorizationserver.auth | ||
|
||
import com.example.authorizationserver.props.LoginProperties | ||
import com.example.authorizationserver.props.ServerProperties | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.core.annotation.Order | ||
import org.springframework.http.MediaType | ||
import org.springframework.security.config.Customizer.withDefaults | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity | ||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration | ||
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer | ||
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings | ||
import org.springframework.security.oauth2.server.authorization.token.* | ||
import org.springframework.security.web.SecurityFilterChain | ||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint | ||
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher | ||
import java.util.* | ||
|
||
/**********************************************************************************************************************/ | ||
/********************************************* AUTHORIZATION SERVER CONFIGURATION *************************************/ | ||
/**********************************************************************************************************************/ | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
internal class AuthServerConfig ( | ||
private val serverProperties: ServerProperties, | ||
private val loginProperties: LoginProperties | ||
) { | ||
|
||
@Bean | ||
@Order(1) | ||
@Throws(Exception::class) | ||
/* security filter chain for protocol endpoints */ | ||
fun authorizationServerSecurityFilterChain(http: HttpSecurity): SecurityFilterChain { | ||
|
||
// disable csrf | ||
http.csrf { csrf -> csrf.disable() } | ||
|
||
// apply default http security settings to oauth 2.0 (e.g. default endpoints) | ||
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http) | ||
|
||
// enable OpenID Connect 1.0 | ||
http.getConfigurer(OAuth2AuthorizationServerConfigurer::class.java) | ||
.oidc(withDefaults()) | ||
|
||
// unauthenticated exception handler | ||
// redirect to the login form page when not authenticated | ||
http.exceptionHandling { exceptionHandling -> | ||
exceptionHandling.defaultAuthenticationEntryPointFor( | ||
LoginUrlAuthenticationEntryPoint(loginProperties.LOGIN_FORM_URL), | ||
MediaTypeRequestMatcher(MediaType.TEXT_HTML) | ||
) | ||
} | ||
|
||
return http.build() | ||
} | ||
|
||
@Bean | ||
// for configuring Spring Authorization Server (e.g. customising URLs for exposed endpoints) | ||
fun authorizationServerSettings(): AuthorizationServerSettings { | ||
return AuthorizationServerSettings.builder() | ||
.issuer(serverProperties.inHouseIssuerUri) | ||
.build() | ||
} | ||
|
||
} | ||
|
||
/**********************************************************************************************************************/ | ||
/**************************************************** END OF KOTLIN ***************************************************/ | ||
/**********************************************************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
package com.example.authorizationserver.auth | ||
|
||
import com.example.authorizationserver.auth.csrf.CsrfProtectionMatcher | ||
import com.example.authorizationserver.auth.filters.DocDbAuthenticationFilter | ||
import com.example.authorizationserver.auth.handlers.DefaultAccessDeniedHandler | ||
import com.example.authorizationserver.auth.handlers.SocialLoginSuccessHandler | ||
import com.example.authorizationserver.auth.repositories.tokens.CustomServletCsrfTokenRepository | ||
//import com.example.authorizationserver.auth.repositories.tokens.RedisRememberMeTokenRepository | ||
import com.example.authorizationserver.auth.requestcache.ServletRequestCache | ||
import com.example.authorizationserver.auth.csrf.CustomCsrfAuthenticationStrategy | ||
import com.example.authorizationserver.auth.sessions.CustomInvalidSessionStrategy | ||
import com.example.authorizationserver.auth.sessions.CustomSessionAuthenticationStrategy | ||
import com.example.authorizationserver.props.LogoutProperties | ||
import com.example.authorizationserver.props.SessionProperties | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.core.annotation.Order | ||
import org.springframework.security.config.annotation.web.builders.HttpSecurity | ||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity | ||
import org.springframework.security.config.http.SessionCreationPolicy | ||
import org.springframework.security.oauth2.client.* | ||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository | ||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository | ||
import org.springframework.security.web.SecurityFilterChain | ||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter | ||
import org.springframework.security.web.authentication.logout.HeaderWriterLogoutHandler | ||
import org.springframework.security.web.context.SecurityContextRepository | ||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter | ||
import org.springframework.security.web.header.writers.ClearSiteDataHeaderWriter.Directive.COOKIES | ||
//import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession | ||
//import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices | ||
|
||
/**********************************************************************************************************************/ | ||
/*********************************************** DEFAULT SECURITY CONFIGURATION ***************************************/ | ||
/**********************************************************************************************************************/ | ||
|
||
@Configuration | ||
@EnableWebSecurity | ||
//@EnableRedisHttpSession( ) | ||
internal class DefaultSecurityConfig () { | ||
|
||
@Autowired | ||
private lateinit var servletClientRegistrationRepository: ClientRegistrationRepository | ||
|
||
@Autowired | ||
private lateinit var servletAuthorizedClientRepository: OAuth2AuthorizedClientRepository | ||
|
||
@Autowired | ||
private lateinit var servletAuthorizedClientService: OAuth2AuthorizedClientService | ||
|
||
@Bean | ||
@Order(2) | ||
@Throws(Exception::class) | ||
/* security filter chain for authentication & authorization */ | ||
fun defaultSecurityFilterChain( | ||
http: HttpSecurity, | ||
customServletCsrfTokenRepository : CustomServletCsrfTokenRepository, | ||
customCsrfAuthenticationStrategy: CustomCsrfAuthenticationStrategy, | ||
csrfProtectionMatcher: CsrfProtectionMatcher, | ||
// sessionRememberMeServices: SpringSessionRememberMeServices, | ||
socialLoginSuccessHandler: SocialLoginSuccessHandler, | ||
docDbAuthenticationFilter: DocDbAuthenticationFilter, | ||
servletRequestCache: ServletRequestCache, | ||
customSecurityContextRepository: SecurityContextRepository, | ||
sessionProperties: SessionProperties, | ||
customInvalidSessionStrategy: CustomInvalidSessionStrategy, | ||
customSessionAuthenticationStrategy: CustomSessionAuthenticationStrategy, | ||
// redisRememberMeTokenRepository: RedisRememberMeTokenRepository, | ||
logoutProperties: LogoutProperties, | ||
accessDeniedHandler: DefaultAccessDeniedHandler, | ||
): SecurityFilterChain { | ||
|
||
// enable csrf | ||
http.csrf { csrf -> | ||
csrf.csrfTokenRepository(customServletCsrfTokenRepository) | ||
csrf.sessionAuthenticationStrategy(customCsrfAuthenticationStrategy) | ||
csrf.requireCsrfProtectionMatcher(csrfProtectionMatcher) | ||
} | ||
|
||
// setup session management - use stateless, and set other configurations | ||
http.sessionManagement { session -> | ||
// not truly stateless since HttpSessionSecurityContextRepository is used | ||
session.sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
// session.enableSessionUrlRewriting(false) | ||
// session.invalidSessionStrategy(customInvalidSessionStrategy) | ||
// session.sessionAuthenticationStrategy(customSessionAuthenticationStrategy) | ||
} | ||
|
||
// creates a more persistent rememberMe token, that isn't lost when browser closes | ||
// (unlike a session cookie, that will be lost) | ||
// http.rememberMe { rememberMe -> | ||
// rememberMe.rememberMeServices(sessionRememberMeServices) | ||
// rememberMe.useSecureCookie(false) // scope is not just on secure connections | ||
// rememberMe.key(securityProperties.rememberMeKey) | ||
// rememberMe.rememberMeCookieName("REMEMBER-ME-SESSIONID") | ||
// rememberMe.tokenRepository(redisRememberMeTokenRepository) | ||
// // rememberMe.userDetailsService() - NEED TO IMPLEMENT | ||
// } | ||
|
||
// apply security context repository | ||
http.securityContext { context -> | ||
context.securityContextRepository(customSecurityContextRepository) | ||
} | ||
|
||
// configure request cache | ||
http.requestCache { requestCache -> | ||
requestCache.requestCache(servletRequestCache) | ||
} | ||
|
||
// form login handles the redirect to the login page from earlier filter chain | ||
http.formLogin { formLogin -> | ||
formLogin | ||
.permitAll() | ||
} | ||
|
||
// oauth2.0 client login (google) | ||
http.oauth2Login { oauth -> | ||
oauth.clientRegistrationRepository(servletClientRegistrationRepository) | ||
oauth.authorizedClientRepository(servletAuthorizedClientRepository) | ||
oauth.authorizedClientService(servletAuthorizedClientService) | ||
oauth.successHandler(socialLoginSuccessHandler) | ||
} | ||
|
||
// apply DocDb authentication filter | ||
http.addFilterBefore( | ||
docDbAuthenticationFilter, | ||
UsernamePasswordAuthenticationFilter::class.java | ||
) | ||
|
||
// authorizations (lock all endpoints apart from) | ||
http.authorizeHttpRequests { authorize -> | ||
// login endpoint | ||
authorize.requestMatchers("/login/**").permitAll() | ||
// logout endpoint | ||
authorize.requestMatchers("/logout/**").permitAll() | ||
// authorization endpoints | ||
authorize.requestMatchers("/oauth2/**").permitAll() | ||
// userinfo endpoint | ||
authorize.requestMatchers("/userinfo").permitAll() | ||
// logout endpoint | ||
authorize.requestMatchers("/connect/logout").permitAll() | ||
// all other endpoints | ||
authorize.anyRequest().authenticated() | ||
} | ||
|
||
// perform cleanup operations on logout (invalidate session, remove cookies & authentication object) | ||
// (note: this does not invalidate access or refresh tokens - they expire whenever they expire) | ||
http.logout { logout -> | ||
logout.logoutUrl(logoutProperties.LOGOUT_URL) | ||
logout.invalidateHttpSession(logoutProperties.INVALIDATE_HTTP_SESSION) | ||
logout.clearAuthentication(logoutProperties.CLEAR_AUTHENTICATION) | ||
logout.deleteCookies(sessionProperties.SESSION_COOKIE_NAME) | ||
logout.addLogoutHandler(HeaderWriterLogoutHandler(ClearSiteDataHeaderWriter(COOKIES))) | ||
logout.permitAll() | ||
} | ||
|
||
// unauthorized exception handler | ||
http.exceptionHandling { exceptionHandling -> | ||
exceptionHandling.accessDeniedHandler(accessDeniedHandler) | ||
} | ||
|
||
return http.build() | ||
} | ||
|
||
} | ||
|
||
/**********************************************************************************************************************/ | ||
/**************************************************** END OF KOTLIN ***************************************************/ | ||
/**********************************************************************************************************************/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.example.authorizationserver.auth | ||
|
||
import org.apache.catalina.Context | ||
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer | ||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.Configuration | ||
import org.springframework.context.annotation.Profile | ||
|
||
/**********************************************************************************************************************/ | ||
/*********************************************** SERVLET CONFIGURATION ************************************************/ | ||
/**********************************************************************************************************************/ | ||
|
||
@Configuration | ||
@Profile("ssl") // only active when 'ssl' profile is active | ||
internal class TomcatConfig { | ||
@Bean | ||
fun tomcatCustomizer(): TomcatServletWebServerFactory { | ||
val factory = TomcatServletWebServerFactory() | ||
|
||
// disable SSL | ||
factory.ssl = null | ||
|
||
// customize session timeout | ||
factory.addContextCustomizers(TomcatContextCustomizer { context: Context -> | ||
context.sessionTimeout = 30 // (in minutes) | ||
}) | ||
|
||
return factory | ||
} | ||
|
||
} | ||
|
||
/**********************************************************************************************************************/ | ||
/**************************************************** END OF KOTLIN ***************************************************/ | ||
/**********************************************************************************************************************/ |
Oops, something went wrong.