Idiomatic Kotlin DSL for configuring HTTP security
Issue: gh-5558
This commit is contained in:
committed by
GitHub
parent
e306482a96
commit
2df1099da5
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
|
||||
abstract class AbstractRequestMatcherDsl {
|
||||
|
||||
/**
|
||||
* Matches any request.
|
||||
*/
|
||||
val anyRequest: RequestMatcher = AnyRequestMatcher.INSTANCE
|
||||
|
||||
protected data class MatcherAuthorizationRule(val matcher: RequestMatcher,
|
||||
override val rule: String) : AuthorizationRule(rule)
|
||||
|
||||
protected data class PatternAuthorizationRule(val pattern: String,
|
||||
val patternType: PatternType,
|
||||
val servletPath: String?,
|
||||
override val rule: String) : AuthorizationRule(rule)
|
||||
|
||||
protected abstract class AuthorizationRule(open val rule: String)
|
||||
|
||||
protected enum class PatternType {
|
||||
ANT, MVC
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationProvider
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.AnonymousConfigurer
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] anonymous authentication using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property key the key to identify tokens created for anonymous authentication
|
||||
* @property principal the principal for [Authentication] objects of anonymous users
|
||||
* @property authorities the [Authentication.getAuthorities] for anonymous users
|
||||
* @property authenticationProvider the [AuthenticationProvider] used to validate an
|
||||
* anonymous user
|
||||
* @property authenticationFilter the [AnonymousAuthenticationFilter] used to populate
|
||||
* an anonymous user.
|
||||
*/
|
||||
class AnonymousDsl {
|
||||
var key: String? = null
|
||||
var principal: Any? = null
|
||||
var authorities: List<GrantedAuthority>? = null
|
||||
var authenticationProvider: AuthenticationProvider? = null
|
||||
var authenticationFilter: AnonymousAuthenticationFilter? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable anonymous authentication
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (AnonymousConfigurer<HttpSecurity>) -> Unit {
|
||||
return { anonymous ->
|
||||
key?.also { anonymous.key(key) }
|
||||
principal?.also { anonymous.principal(principal) }
|
||||
authorities?.also { anonymous.authorities(authorities) }
|
||||
authenticationProvider?.also { anonymous.authenticationProvider(authenticationProvider) }
|
||||
authenticationFilter?.also { anonymous.authenticationFilter(authenticationFilter) }
|
||||
if (disabled) {
|
||||
anonymous.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.util.ClassUtils
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] request authorization using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
*/
|
||||
class AuthorizeRequestsDsl : AbstractRequestMatcherDsl() {
|
||||
private val authorizationRules = mutableListOf<AuthorizationRule>()
|
||||
|
||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
||||
private val MVC_PRESENT = ClassUtils.isPresent(
|
||||
HANDLER_MAPPING_INTROSPECTOR,
|
||||
AuthorizeRequestsDsl::class.java.classLoader)
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule.
|
||||
*
|
||||
* @param matches the [RequestMatcher] to match incoming requests against
|
||||
* @param access the SpEL expression to secure the matching request
|
||||
* (i.e. "hasAuthority('ROLE_USER') and hasAuthority('ROLE_SUPER')")
|
||||
*/
|
||||
fun authorize(matches: RequestMatcher = AnyRequestMatcher.INSTANCE,
|
||||
access: String = "authenticated") {
|
||||
authorizationRules.add(MatcherAuthorizationRule(matches, access))
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param access the SpEL expression to secure the matching request
|
||||
* (i.e. "hasAuthority('ROLE_USER') and hasAuthority('ROLE_SUPER')")
|
||||
*/
|
||||
fun authorize(pattern: String, access: String = "authenticated") {
|
||||
if (MVC_PRESENT) {
|
||||
authorizationRules.add(PatternAuthorizationRule(pattern, PatternType.MVC, null, access))
|
||||
} else {
|
||||
authorizationRules.add(PatternAuthorizationRule(pattern, PatternType.ANT, null, access))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param servletPath the servlet path to match incoming requests against. This
|
||||
* only applies when using an MVC pattern matcher.
|
||||
* @param access the SpEL expression to secure the matching request
|
||||
* (i.e. "hasAuthority('ROLE_USER') and hasAuthority('ROLE_SUPER')")
|
||||
*/
|
||||
fun authorize(pattern: String, servletPath: String, access: String = "authenticated") {
|
||||
if (MVC_PRESENT) {
|
||||
authorizationRules.add(PatternAuthorizationRule(pattern, PatternType.MVC, servletPath, access))
|
||||
} else {
|
||||
authorizationRules.add(PatternAuthorizationRule(pattern, PatternType.ANT, servletPath, access))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify that URLs require a particular authority.
|
||||
*
|
||||
* @param authority the authority to require (i.e. ROLE_USER, ROLE_ADMIN, etc).
|
||||
* @return the SpEL expression "hasAuthority" with the given authority as a
|
||||
* parameter
|
||||
*/
|
||||
fun hasAuthority(authority: String) = "hasAuthority('$authority')"
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by anyone.
|
||||
*/
|
||||
val permitAll = "permitAll"
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by anonymous users.
|
||||
*/
|
||||
val anonymous = "anonymous"
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by users that have been remembered.
|
||||
*/
|
||||
val rememberMe = "rememberMe"
|
||||
|
||||
/**
|
||||
* Specify that URLs are not allowed by anyone.
|
||||
*/
|
||||
val denyAll = "denyAll"
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by any authenticated user.
|
||||
*/
|
||||
val authenticated = "authenticated"
|
||||
|
||||
/**
|
||||
* Specify that URLs are allowed by users who have authenticated and were not
|
||||
* "remembered".
|
||||
*/
|
||||
val fullyAuthenticated = "fullyAuthenticated"
|
||||
|
||||
internal fun get(): (ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry) -> Unit {
|
||||
return { requests ->
|
||||
authorizationRules.forEach { rule ->
|
||||
when (rule) {
|
||||
is MatcherAuthorizationRule -> requests.requestMatchers(rule.matcher).access(rule.rule)
|
||||
is PatternAuthorizationRule -> {
|
||||
when (rule.patternType) {
|
||||
PatternType.ANT -> requests.antMatchers(rule.pattern).access(rule.rule)
|
||||
PatternType.MVC -> {
|
||||
val mvcMatchersAuthorizeUrl = requests.mvcMatchers(rule.pattern)
|
||||
rule.servletPath?.also { mvcMatchersAuthorizeUrl.servletPath(rule.servletPath) }
|
||||
mvcMatchersAuthorizeUrl.access(rule.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.CorsConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] CORS using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
*/
|
||||
class CorsDsl {
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable CORS.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (CorsConfigurer<HttpSecurity>) -> Unit {
|
||||
return { cors ->
|
||||
if (disabled) {
|
||||
cors.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.CsrfConfigurer
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
|
||||
import org.springframework.security.web.csrf.CsrfTokenRepository
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] CSRF protection
|
||||
* using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property csrfTokenRepository the [CsrfTokenRepository] to use.
|
||||
* @property requireCsrfProtectionMatcher specify the [RequestMatcher] to use for
|
||||
* determining when CSRF should be applied.
|
||||
* @property sessionAuthenticationStrategy the [SessionAuthenticationStrategy] to use.
|
||||
*/
|
||||
class CsrfDsl {
|
||||
var csrfTokenRepository: CsrfTokenRepository? = null
|
||||
var requireCsrfProtectionMatcher: RequestMatcher? = null
|
||||
var sessionAuthenticationStrategy: SessionAuthenticationStrategy? = null
|
||||
|
||||
private var ignoringAntMatchers: Array<out String>? = null
|
||||
private var ignoringRequestMatchers: Array<out RequestMatcher>? = null
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Allows specifying [HttpServletRequest]s that should not use CSRF Protection
|
||||
* even if they match the [requireCsrfProtectionMatcher].
|
||||
*
|
||||
* @param antMatchers the ANT pattern matchers that should not use CSRF
|
||||
* protection
|
||||
*/
|
||||
fun ignoringAntMatchers(vararg antMatchers: String) {
|
||||
ignoringAntMatchers = antMatchers
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows specifying [HttpServletRequest]s that should not use CSRF Protection
|
||||
* even if they match the [requireCsrfProtectionMatcher].
|
||||
*
|
||||
* @param requestMatchers the request matchers that should not use CSRF
|
||||
* protection
|
||||
*/
|
||||
fun ignoringRequestMatchers(vararg requestMatchers: RequestMatcher) {
|
||||
ignoringRequestMatchers = requestMatchers
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable CSRF protection
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (CsrfConfigurer<HttpSecurity>) -> Unit {
|
||||
return { csrf ->
|
||||
csrfTokenRepository?.also { csrf.csrfTokenRepository(csrfTokenRepository) }
|
||||
requireCsrfProtectionMatcher?.also { csrf.requireCsrfProtectionMatcher(requireCsrfProtectionMatcher) }
|
||||
sessionAuthenticationStrategy?.also { csrf.sessionAuthenticationStrategy(sessionAuthenticationStrategy) }
|
||||
ignoringAntMatchers?.also { csrf.ignoringAntMatchers(*ignoringAntMatchers!!) }
|
||||
ignoringRequestMatchers?.also { csrf.ignoringRequestMatchers(*ignoringRequestMatchers!!) }
|
||||
if (disabled) {
|
||||
csrf.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.ExceptionHandlingConfigurer
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] exception handling using idiomatic Kotlin
|
||||
* code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property accessDeniedPage the URL to the access denied page
|
||||
* @property accessDeniedHandler the [AccessDeniedHandler] to use
|
||||
* @property authenticationEntryPoint the [AuthenticationEntryPoint] to use
|
||||
*/
|
||||
class ExceptionHandlingDsl {
|
||||
var accessDeniedPage: String? = null
|
||||
var accessDeniedHandler: AccessDeniedHandler? = null
|
||||
var authenticationEntryPoint: AuthenticationEntryPoint? = null
|
||||
|
||||
private var defaultDeniedHandlerMappings: LinkedHashMap<RequestMatcher, AccessDeniedHandler> = linkedMapOf()
|
||||
private var defaultEntryPointMappings: LinkedHashMap<RequestMatcher, AuthenticationEntryPoint> = linkedMapOf()
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Sets a default [AccessDeniedHandler] to be used which prefers being
|
||||
* invoked for the provided [RequestMatcher].
|
||||
*
|
||||
* @param deniedHandler the [AccessDeniedHandler] to use
|
||||
* @param preferredMatcher the [RequestMatcher] for this default
|
||||
* [AccessDeniedHandler]
|
||||
*/
|
||||
fun defaultAccessDeniedHandlerFor(deniedHandler: AccessDeniedHandler, preferredMatcher: RequestMatcher) {
|
||||
defaultDeniedHandlerMappings[preferredMatcher] = deniedHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default [AuthenticationEntryPoint] to be used which prefers being
|
||||
* invoked for the provided [RequestMatcher].
|
||||
*
|
||||
* @param entryPoint the [AuthenticationEntryPoint] to use
|
||||
* @param preferredMatcher the [RequestMatcher] for this default
|
||||
* [AccessDeniedHandler]
|
||||
*/
|
||||
fun defaultAuthenticationEntryPointFor(entryPoint: AuthenticationEntryPoint, preferredMatcher: RequestMatcher) {
|
||||
defaultEntryPointMappings[preferredMatcher] = entryPoint
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable exception handling.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (ExceptionHandlingConfigurer<HttpSecurity>) -> Unit {
|
||||
return { exceptionHandling ->
|
||||
accessDeniedPage?.also { exceptionHandling.accessDeniedPage(accessDeniedPage) }
|
||||
accessDeniedHandler?.also { exceptionHandling.accessDeniedHandler(accessDeniedHandler) }
|
||||
authenticationEntryPoint?.also { exceptionHandling.authenticationEntryPoint(authenticationEntryPoint) }
|
||||
defaultDeniedHandlerMappings.forEach { (matcher, handler) ->
|
||||
exceptionHandling.defaultAccessDeniedHandlerFor(handler, matcher)
|
||||
}
|
||||
defaultEntryPointMappings.forEach { (matcher, entryPoint) ->
|
||||
exceptionHandling.defaultAuthenticationEntryPointFor(entryPoint, matcher)
|
||||
}
|
||||
if (disabled) {
|
||||
exceptionHandling.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] form login using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property loginPage the login page to redirect to if authentication is required (i.e.
|
||||
* "/login")
|
||||
* @property authenticationSuccessHandler the [AuthenticationSuccessHandler] used after
|
||||
* authentication success
|
||||
* @property authenticationFailureHandler the [AuthenticationFailureHandler] used after
|
||||
* authentication success
|
||||
* @property failureUrl the URL to send users if authentication fails
|
||||
* @property loginProcessingUrl the URL to validate the credentials
|
||||
* @property permitAll whether to grant access to the urls for [failureUrl] as well as
|
||||
* for the [HttpSecurityBuilder], the [loginPage] and [loginProcessingUrl] for every user
|
||||
*/
|
||||
class FormLoginDsl {
|
||||
var loginPage: String? = null
|
||||
var authenticationSuccessHandler: AuthenticationSuccessHandler? = null
|
||||
var authenticationFailureHandler: AuthenticationFailureHandler? = null
|
||||
var failureUrl: String? = null
|
||||
var loginProcessingUrl: String? = null
|
||||
var permitAll: Boolean? = null
|
||||
|
||||
private var defaultSuccessUrlOption: Pair<String, Boolean>? = null
|
||||
|
||||
/**
|
||||
* Grants access to the urls for [failureUrl] as well as for the [HttpSecurityBuilder], the
|
||||
* [loginPage] and [loginProcessingUrl] for every user.
|
||||
*/
|
||||
fun permitAll() {
|
||||
permitAll = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies where users will be redirected after authenticating successfully if
|
||||
* they have not visited a secured page prior to authenticating or [alwaysUse]
|
||||
* is true.
|
||||
*
|
||||
* @param defaultSuccessUrl the default success url
|
||||
* @param alwaysUse true if the [defaultSuccessUrl] should be used after
|
||||
* authentication despite if a protected page had been previously visited
|
||||
*/
|
||||
fun defaultSuccessUrl(defaultSuccessUrl: String, alwaysUse: Boolean) {
|
||||
defaultSuccessUrlOption = Pair(defaultSuccessUrl, alwaysUse)
|
||||
}
|
||||
|
||||
internal fun get(): (FormLoginConfigurer<HttpSecurity>) -> Unit {
|
||||
return { login ->
|
||||
loginPage?.also { login.loginPage(loginPage) }
|
||||
failureUrl?.also { login.failureUrl(failureUrl) }
|
||||
loginProcessingUrl?.also { login.loginProcessingUrl(loginProcessingUrl) }
|
||||
permitAll?.also { login.permitAll(permitAll!!) }
|
||||
defaultSuccessUrlOption?.also {
|
||||
login.defaultSuccessUrl(defaultSuccessUrlOption!!.first, defaultSuccessUrlOption!!.second)
|
||||
}
|
||||
authenticationSuccessHandler?.also { login.successHandler(authenticationSuccessHandler) }
|
||||
authenticationFailureHandler?.also { login.failureHandler(authenticationFailureHandler) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
import org.springframework.security.config.web.servlet.headers.*
|
||||
import org.springframework.security.web.header.writers.*
|
||||
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] headers using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property defaultsDisabled whether all of the default headers should be included in the response
|
||||
*/
|
||||
class HeadersDsl {
|
||||
private var contentTypeOptions: ((HeadersConfigurer<HttpSecurity>.ContentTypeOptionsConfig) -> Unit)? = null
|
||||
private var xssProtection: ((HeadersConfigurer<HttpSecurity>.XXssConfig) -> Unit)? = null
|
||||
private var cacheControl: ((HeadersConfigurer<HttpSecurity>.CacheControlConfig) -> Unit)? = null
|
||||
private var hsts: ((HeadersConfigurer<HttpSecurity>.HstsConfig) -> Unit)? = null
|
||||
private var frameOptions: ((HeadersConfigurer<HttpSecurity>.FrameOptionsConfig) -> Unit)? = null
|
||||
private var hpkp: ((HeadersConfigurer<HttpSecurity>.HpkpConfig) -> Unit)? = null
|
||||
private var contentSecurityPolicy: ((HeadersConfigurer<HttpSecurity>.ContentSecurityPolicyConfig) -> Unit)? = null
|
||||
private var referrerPolicy: ((HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit)? = null
|
||||
private var featurePolicyDirectives: String? = null
|
||||
|
||||
var defaultsDisabled: Boolean? = null
|
||||
|
||||
/**
|
||||
* Configures the [XContentTypeOptionsHeaderWriter] which inserts the <a href=
|
||||
* "https://msdn.microsoft.com/en-us/library/ie/gg622941(v=vs.85).aspx"
|
||||
* >X-Content-Type-Options header</a>
|
||||
*
|
||||
* @param contentTypeOptionsConfig the customization to apply to the header
|
||||
*/
|
||||
fun contentTypeOptions(contentTypeOptionsConfig: ContentTypeOptionsDsl.() -> Unit) {
|
||||
this.contentTypeOptions = ContentTypeOptionsDsl().apply(contentTypeOptionsConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* <strong>Note this is not comprehensive XSS protection!</strong>
|
||||
*
|
||||
* <p>
|
||||
* Allows customizing the [XXssProtectionHeaderWriter] which adds the <a href=
|
||||
* "https://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx"
|
||||
* >X-XSS-Protection header</a>
|
||||
* </p>
|
||||
*
|
||||
* @param xssProtectionConfig the customization to apply to the header
|
||||
*/
|
||||
fun xssProtection(xssProtectionConfig: XssProtectionConfigDsl.() -> Unit) {
|
||||
this.xssProtection = XssProtectionConfigDsl().apply(xssProtectionConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows customizing the [CacheControlHeadersWriter]. Specifically it adds the
|
||||
* following headers:
|
||||
* <ul>
|
||||
* <li>Cache-Control: no-cache, no-store, max-age=0, must-revalidate</li>
|
||||
* <li>Pragma: no-cache</li>
|
||||
* <li>Expires: 0</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param cacheControlConfig the customization to apply to the header
|
||||
*/
|
||||
fun cacheControl(cacheControlConfig: CacheControlDsl.() -> Unit) {
|
||||
this.cacheControl = CacheControlDsl().apply(cacheControlConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows customizing the [HstsHeaderWriter] which provides support for <a
|
||||
* href="https://tools.ietf.org/html/rfc6797">HTTP Strict Transport Security
|
||||
* (HSTS)</a>.
|
||||
*
|
||||
* @param hstsConfig the customization to apply to the header
|
||||
*/
|
||||
fun httpStrictTransportSecurity(hstsConfig: HttpStrictTransportSecurityDsl.() -> Unit) {
|
||||
this.hsts = HttpStrictTransportSecurityDsl().apply(hstsConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows customizing the [XFrameOptionsHeaderWriter] which add the X-Frame-Options
|
||||
* header.
|
||||
*
|
||||
* @param frameOptionsConfig the customization to apply to the header
|
||||
*/
|
||||
fun frameOptions(frameOptionsConfig: FrameOptionsDsl.() -> Unit) {
|
||||
this.frameOptions = FrameOptionsDsl().apply(frameOptionsConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows customizing the [HpkpHeaderWriter] which provides support for <a
|
||||
* href="https://tools.ietf.org/html/rfc7469">HTTP Public Key Pinning (HPKP)</a>.
|
||||
*
|
||||
* @param hpkpConfig the customization to apply to the header
|
||||
*/
|
||||
fun httpPublicKeyPinning(hpkpConfig: HttpPublicKeyPinningDsl.() -> Unit) {
|
||||
this.hpkp = HttpPublicKeyPinningDsl().apply(hpkpConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://www.w3.org/TR/CSP2/">Content Security Policy (CSP) Level 2</a>.
|
||||
*
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the Content-Security-Policy header in the response
|
||||
* using the supplied security policy directive(s).
|
||||
* </p>
|
||||
*
|
||||
* @param contentSecurityPolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun contentSecurityPolicy(contentSecurityPolicyConfig: ContentSecurityPolicyDsl.() -> Unit) {
|
||||
this.contentSecurityPolicy = ContentSecurityPolicyDsl().apply(contentSecurityPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://www.w3.org/TR/referrer-policy/">Referrer Policy</a>.
|
||||
*
|
||||
* <p>
|
||||
* Configuration is provided to the [ReferrerPolicyHeaderWriter] which support the writing
|
||||
* of the header as detailed in the W3C Technical Report:
|
||||
* </p>
|
||||
* <ul>
|
||||
* <li>Referrer-Policy</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param referrerPolicyConfig the customization to apply to the header
|
||||
*/
|
||||
fun referrerPolicy(referrerPolicyConfig: ReferrerPolicyDsl.() -> Unit) {
|
||||
this.referrerPolicy = ReferrerPolicyDsl().apply(referrerPolicyConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuration for <a href="https://wicg.github.io/feature-policy/">Feature
|
||||
* Policy</a>.
|
||||
*
|
||||
* <p>
|
||||
* Calling this method automatically enables (includes) the Feature-Policy
|
||||
* header in the response using the supplied policy directive(s).
|
||||
* <p>
|
||||
*
|
||||
* @param policyDirectives policyDirectives the security policy directive(s)
|
||||
*/
|
||||
fun featurePolicy(policyDirectives: String) {
|
||||
this.featurePolicyDirectives = policyDirectives
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>) -> Unit {
|
||||
return { headers ->
|
||||
defaultsDisabled?.also {
|
||||
if (defaultsDisabled!!) {
|
||||
headers.defaultsDisabled()
|
||||
}
|
||||
}
|
||||
contentTypeOptions?.also {
|
||||
headers.contentTypeOptions(contentTypeOptions)
|
||||
}
|
||||
xssProtection?.also {
|
||||
headers.xssProtection(xssProtection)
|
||||
}
|
||||
cacheControl?.also {
|
||||
headers.cacheControl(cacheControl)
|
||||
}
|
||||
hsts?.also {
|
||||
headers.httpStrictTransportSecurity(hsts)
|
||||
}
|
||||
frameOptions?.also {
|
||||
headers.frameOptions(frameOptions)
|
||||
}
|
||||
hpkp?.also {
|
||||
headers.httpPublicKeyPinning(hpkp)
|
||||
}
|
||||
contentSecurityPolicy?.also {
|
||||
headers.contentSecurityPolicy(contentSecurityPolicy)
|
||||
}
|
||||
referrerPolicy?.also {
|
||||
headers.referrerPolicy(referrerPolicy)
|
||||
}
|
||||
featurePolicyDirectives?.also {
|
||||
headers.featurePolicy(featurePolicyDirectives)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HttpBasicConfigurer
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] basic authentication using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property realmName the HTTP Basic realm to use. If [authenticationEntryPoint]
|
||||
* has been invoked, invoking this method will result in an error.
|
||||
* @property authenticationEntryPoint the [AuthenticationEntryPoint] to be populated on
|
||||
* [BasicAuthenticationFilter] in the event that authentication fails.
|
||||
* @property authenticationDetailsSource the custom [AuthenticationDetailsSource] to use for
|
||||
* basic authentication.
|
||||
*/
|
||||
class HttpBasicDsl {
|
||||
var realmName: String? = null
|
||||
var authenticationEntryPoint: AuthenticationEntryPoint? = null
|
||||
var authenticationDetailsSource: AuthenticationDetailsSource<HttpServletRequest, *>? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disables HTTP basic authentication
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HttpBasicConfigurer<HttpSecurity>) -> Unit {
|
||||
return { httpBasic ->
|
||||
realmName?.also { httpBasic.realmName(realmName) }
|
||||
authenticationEntryPoint?.also { httpBasic.authenticationEntryPoint(authenticationEntryPoint) }
|
||||
authenticationDetailsSource?.also { httpBasic.authenticationDetailsSource(authenticationDetailsSource) }
|
||||
if (disabled) {
|
||||
httpBasic.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,651 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.context.ApplicationContext
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.util.ClassUtils
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* Configures [HttpSecurity] using a [HttpSecurity Kotlin DSL][HttpSecurityDsl].
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* authorizeRequests {
|
||||
* request("/public", permitAll)
|
||||
* request(anyRequest, authenticated)
|
||||
* }
|
||||
* formLogin {
|
||||
* loginPage = "/log-in"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @param httpConfiguration the configurations to apply to [HttpSecurity]
|
||||
*/
|
||||
operator fun HttpSecurity.invoke(httpConfiguration: HttpSecurityDsl.() -> Unit) =
|
||||
HttpSecurityDsl(this, httpConfiguration).build()
|
||||
|
||||
/**
|
||||
* An [HttpSecurity] Kotlin DSL created by [`http { }`][invoke]
|
||||
* in order to configure [HttpSecurity] using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @param http the [HttpSecurity] which all configurations will be applied to
|
||||
* @param init the configurations to apply to the provided [HttpSecurity]
|
||||
*/
|
||||
class HttpSecurityDsl(private val http: HttpSecurity, private val init: HttpSecurityDsl.() -> Unit) {
|
||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
||||
|
||||
/**
|
||||
* Allows configuring the [HttpSecurity] to only be invoked when matching the
|
||||
* provided pattern.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* securityMatcher("/private/**")
|
||||
* formLogin {
|
||||
* loginPage = "/log-in"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param pattern one or more patterns used to determine whether this
|
||||
* configuration should be invoked.
|
||||
*/
|
||||
fun securityMatcher(vararg pattern: String) {
|
||||
val mvcPresent = ClassUtils.isPresent(
|
||||
HANDLER_MAPPING_INTROSPECTOR,
|
||||
AuthorizeRequestsDsl::class.java.classLoader)
|
||||
this.http.requestMatchers {
|
||||
if (mvcPresent) {
|
||||
it.mvcMatchers(*pattern)
|
||||
} else {
|
||||
it.antMatchers(*pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring the [HttpSecurity] to only be invoked when matching the
|
||||
* provided [RequestMatcher].
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* securityMatcher(AntPathRequestMatcher("/private/**"))
|
||||
* formLogin {
|
||||
* loginPage = "/log-in"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param requestMatcher one or more [RequestMatcher] used to determine whether
|
||||
* this configuration should be invoked.
|
||||
*/
|
||||
fun securityMatcher(vararg requestMatcher: RequestMatcher) {
|
||||
this.http.requestMatchers {
|
||||
it.requestMatchers(*requestMatcher)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables form based authentication.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* formLogin {
|
||||
* loginPage = "/log-in"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param formLoginConfiguration custom configurations to be applied
|
||||
* to the form based authentication
|
||||
* @see [FormLoginDsl]
|
||||
*/
|
||||
fun formLogin(formLoginConfiguration: FormLoginDsl.() -> Unit) {
|
||||
val loginCustomizer = FormLoginDsl().apply(formLoginConfiguration).get()
|
||||
this.http.formLogin(loginCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows restricting access based upon the [HttpServletRequest]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* authorizeRequests {
|
||||
* request("/public", permitAll)
|
||||
* request(anyRequest, authenticated)
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param authorizeRequestsConfiguration custom configuration that specifies
|
||||
* access for requests
|
||||
* @see [AuthorizeRequestsDsl]
|
||||
*/
|
||||
fun authorizeRequests(authorizeRequestsConfiguration: AuthorizeRequestsDsl.() -> Unit) {
|
||||
val authorizeRequestsCustomizer = AuthorizeRequestsDsl().apply(authorizeRequestsConfiguration).get()
|
||||
this.http.authorizeRequests(authorizeRequestsCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables HTTP basic authentication.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* httpBasic {
|
||||
* realmName = "Custom Realm"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param httpBasicConfiguration custom configurations to be applied to the
|
||||
* HTTP basic authentication
|
||||
* @see [HttpBasicDsl]
|
||||
*/
|
||||
fun httpBasic(httpBasicConfiguration: HttpBasicDsl.() -> Unit) {
|
||||
val httpBasicCustomizer = HttpBasicDsl().apply(httpBasicConfiguration).get()
|
||||
this.http.httpBasic(httpBasicCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring response headers.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* headers {
|
||||
* referrerPolicy {
|
||||
* policy = ReferrerPolicy.SAME_ORIGIN
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param headersConfiguration custom configurations to configure the
|
||||
* response headers
|
||||
* @see [HeadersDsl]
|
||||
*/
|
||||
fun headers(headersConfiguration: HeadersDsl.() -> Unit) {
|
||||
val headersCustomizer = HeadersDsl().apply(headersConfiguration).get()
|
||||
this.http.headers(headersCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables CORS.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* cors {
|
||||
* disable()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param corsConfiguration custom configurations to configure the
|
||||
* response headers
|
||||
* @see [CorsDsl]
|
||||
*/
|
||||
fun cors(corsConfiguration: CorsDsl.() -> Unit) {
|
||||
val corsCustomizer = CorsDsl().apply(corsConfiguration).get()
|
||||
this.http.cors(corsCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring session management.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* sessionManagement {
|
||||
* invalidSessionUrl = "/invalid-session"
|
||||
* sessionConcurrency {
|
||||
* maximumSessions = 1
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param sessionManagementConfiguration custom configurations to configure
|
||||
* session management
|
||||
* @see [SessionManagementDsl]
|
||||
*/
|
||||
fun sessionManagement(sessionManagementConfiguration: SessionManagementDsl.() -> Unit) {
|
||||
val sessionManagementCustomizer = SessionManagementDsl().apply(sessionManagementConfiguration).get()
|
||||
this.http.sessionManagement(sessionManagementCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring a port mapper.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* portMapper {
|
||||
* map(80, 443)
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param portMapperConfiguration custom configurations to configure
|
||||
* the port mapper
|
||||
* @see [PortMapperDsl]
|
||||
*/
|
||||
fun portMapper(portMapperConfiguration: PortMapperDsl.() -> Unit) {
|
||||
val portMapperCustomizer = PortMapperDsl().apply(portMapperConfiguration).get()
|
||||
this.http.portMapper(portMapperCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring channel security based upon the [HttpServletRequest]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* requiresChannel {
|
||||
* secure("/public", requiresInsecure)
|
||||
* secure(anyRequest, requiresSecure)
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param requiresChannelConfiguration custom configuration that specifies
|
||||
* channel security
|
||||
* @see [RequiresChannelDsl]
|
||||
*/
|
||||
fun requiresChannel(requiresChannelConfiguration: RequiresChannelDsl.() -> Unit) {
|
||||
val requiresChannelCustomizer = RequiresChannelDsl().apply(requiresChannelConfiguration).get()
|
||||
this.http.requiresChannel(requiresChannelCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds X509 based pre authentication to an application
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* x509 { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param x509Configuration custom configuration to apply to the
|
||||
* X509 based pre authentication
|
||||
* @see [X509Dsl]
|
||||
*/
|
||||
fun x509(x509Configuration: X509Dsl.() -> Unit) {
|
||||
val x509Customizer = X509Dsl().apply(x509Configuration).get()
|
||||
this.http.x509(x509Customizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables request caching. Specifically this ensures that requests that
|
||||
* are saved (i.e. after authentication is required) are later replayed.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* requestCache { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param requestCacheConfiguration custom configuration to apply to the
|
||||
* request cache
|
||||
* @see [RequestCacheDsl]
|
||||
*/
|
||||
fun requestCache(requestCacheConfiguration: RequestCacheDsl.() -> Unit) {
|
||||
val requestCacheCustomizer = RequestCacheDsl().apply(requestCacheConfiguration).get()
|
||||
this.http.requestCache(requestCacheCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring exception handling.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* exceptionHandling {
|
||||
* accessDeniedPage = "/access-denied"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param exceptionHandlingConfiguration custom configuration to apply to the
|
||||
* exception handling
|
||||
* @see [ExceptionHandlingDsl]
|
||||
*/
|
||||
fun exceptionHandling(exceptionHandlingConfiguration: ExceptionHandlingDsl.() -> Unit) {
|
||||
val exceptionHandlingCustomizer = ExceptionHandlingDsl().apply(exceptionHandlingConfiguration).get()
|
||||
this.http.exceptionHandling(exceptionHandlingCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables CSRF protection.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* csrf { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param csrfConfiguration custom configuration to apply to CSRF
|
||||
* @see [CsrfDsl]
|
||||
*/
|
||||
fun csrf(csrfConfiguration: CsrfDsl.() -> Unit) {
|
||||
val csrfCustomizer = CsrfDsl().apply(csrfConfiguration).get()
|
||||
this.http.csrf(csrfCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides logout support.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* logout {
|
||||
* logoutUrl = "/log-out"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param logoutConfiguration custom configuration to apply to logout
|
||||
* @see [LogoutDsl]
|
||||
*/
|
||||
fun logout(logoutConfiguration: LogoutDsl.() -> Unit) {
|
||||
val logoutCustomizer = LogoutDsl().apply(logoutConfiguration).get()
|
||||
this.http.logout(logoutCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures authentication support using a SAML 2.0 Service Provider.
|
||||
* A [RelyingPartyRegistrationRepository] is required and must be registered with
|
||||
* the [ApplicationContext] or configured via
|
||||
* [Saml2Dsl.relyingPartyRegistrationRepository]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* saml2Login {
|
||||
* relyingPartyRegistration = getSaml2RelyingPartyRegistration()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param saml2LoginConfiguration custom configuration to configure the
|
||||
* SAML2 service provider
|
||||
* @see [Saml2Dsl]
|
||||
*/
|
||||
fun saml2Login(saml2LoginConfiguration: Saml2Dsl.() -> Unit) {
|
||||
val saml2LoginCustomizer = Saml2Dsl().apply(saml2LoginConfiguration).get()
|
||||
this.http.saml2Login(saml2LoginCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows configuring how an anonymous user is represented.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* anonymous {
|
||||
* authorities = listOf(SimpleGrantedAuthority("ROLE_ANON"))
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param anonymousConfiguration custom configuration to configure the
|
||||
* anonymous user
|
||||
* @see [AnonymousDsl]
|
||||
*/
|
||||
fun anonymous(anonymousConfiguration: AnonymousDsl.() -> Unit) {
|
||||
val anonymousCustomizer = AnonymousDsl().apply(anonymousConfiguration).get()
|
||||
this.http.anonymous(anonymousCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures authentication support using an OAuth 2.0 and/or OpenID Connect 1.0 Provider.
|
||||
* A [ClientRegistrationRepository] is required and must be registered as a Bean or
|
||||
* configured via [OAuth2LoginDsl.clientRegistrationRepository]
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* oauth2Login {
|
||||
* clientRegistrationRepository = getClientRegistrationRepository()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param oauth2LoginConfiguration custom configuration to configure the
|
||||
* OAuth 2.0 Login
|
||||
* @see [OAuth2LoginDsl]
|
||||
*/
|
||||
fun oauth2Login(oauth2LoginConfiguration: OAuth2LoginDsl.() -> Unit) {
|
||||
val oauth2LoginCustomizer = OAuth2LoginDsl().apply(oauth2LoginConfiguration).get()
|
||||
this.http.oauth2Login(oauth2LoginCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures OAuth 2.0 client support.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* oauth2Client { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param oauth2ClientConfiguration custom configuration to configure the
|
||||
* OAuth 2.0 client support
|
||||
* @see [OAuth2ClientDsl]
|
||||
*/
|
||||
fun oauth2Client(oauth2ClientConfiguration: OAuth2ClientDsl.() -> Unit) {
|
||||
val oauth2ClientCustomizer = OAuth2ClientDsl().apply(oauth2ClientConfiguration).get()
|
||||
this.http.oauth2Client(oauth2ClientCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures OAuth 2.0 resource server support.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* http {
|
||||
* oauth2ResourceServer {
|
||||
* jwt { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param oauth2ResourceServerConfiguration custom configuration to configure the
|
||||
* OAuth 2.0 resource server support
|
||||
* @see [OAuth2ResourceServerDsl]
|
||||
*/
|
||||
fun oauth2ResourceServer(oauth2ResourceServerConfiguration: OAuth2ResourceServerDsl.() -> Unit) {
|
||||
val oauth2ResourceServerCustomizer = OAuth2ResourceServerDsl().apply(oauth2ResourceServerConfiguration).get()
|
||||
this.http.oauth2ResourceServer(oauth2ResourceServerCustomizer)
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all configurations to the provided [HttpSecurity]
|
||||
*/
|
||||
internal fun build() {
|
||||
init()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer
|
||||
import org.springframework.security.core.Authentication
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.security.web.authentication.logout.LogoutHandler
|
||||
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler
|
||||
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import java.util.*
|
||||
import javax.servlet.http.HttpSession
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] logout support
|
||||
* using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property clearAuthentication whether the [SecurityContextLogoutHandler] should clear
|
||||
* the [Authentication] at the time of logout.
|
||||
* @property clearAuthentication whether to invalidate the [HttpSession] at the time of logout.
|
||||
* @property logoutUrl the URL that triggers log out to occur.
|
||||
* @property logoutRequestMatcher the [RequestMatcher] that triggers log out to occur.
|
||||
* @property logoutSuccessUrl the URL to redirect to after logout has occurred.
|
||||
* @property logoutSuccessHandler the [LogoutSuccessHandler] to use after logout has occurred.
|
||||
* If this is specified, [logoutSuccessUrl] is ignored.
|
||||
*/
|
||||
class LogoutDsl {
|
||||
var clearAuthentication: Boolean? = null
|
||||
var invalidateHttpSession: Boolean? = null
|
||||
var logoutUrl: String? = null
|
||||
var logoutRequestMatcher: RequestMatcher? = null
|
||||
var logoutSuccessUrl: String? = null
|
||||
var logoutSuccessHandler: LogoutSuccessHandler? = null
|
||||
var permitAll: Boolean? = null
|
||||
|
||||
private var logoutHandlers = mutableListOf<LogoutHandler>()
|
||||
private var deleteCookies: Array<out String>? = null
|
||||
private var defaultLogoutSuccessHandlerMappings: LinkedHashMap<RequestMatcher, LogoutSuccessHandler> = linkedMapOf()
|
||||
private var disabled = false
|
||||
|
||||
|
||||
/**
|
||||
* Adds a [LogoutHandler]. The [SecurityContextLogoutHandler] is added as
|
||||
* the last [LogoutHandler] by default.
|
||||
*
|
||||
* @param logoutHandler the [LogoutHandler] to add
|
||||
*/
|
||||
fun addLogoutHandler(logoutHandler: LogoutHandler) {
|
||||
this.logoutHandlers.add(logoutHandler)
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows specifying the names of cookies to be removed on logout success.
|
||||
*
|
||||
* @param cookieNamesToClear the names of cookies to be removed on logout success.
|
||||
*/
|
||||
fun deleteCookies(vararg cookieNamesToClear: String) {
|
||||
this.deleteCookies = cookieNamesToClear
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default [LogoutSuccessHandler] to be used which prefers being
|
||||
* invoked for the provided [RequestMatcher].
|
||||
*
|
||||
* @param logoutHandler the [LogoutSuccessHandler] to use
|
||||
* @param preferredMatcher the [RequestMatcher] for this default
|
||||
* [AccessDeniedHandler]
|
||||
*/
|
||||
fun defaultLogoutSuccessHandlerFor(logoutHandler: LogoutSuccessHandler, preferredMatcher: RequestMatcher) {
|
||||
defaultLogoutSuccessHandlerMappings[preferredMatcher] = logoutHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables logout
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Grants access to the [logoutSuccessUrl] and the [logoutUrl] for every user.
|
||||
*/
|
||||
fun permitAll() {
|
||||
permitAll = true
|
||||
}
|
||||
|
||||
internal fun get(): (LogoutConfigurer<HttpSecurity>) -> Unit {
|
||||
return { logout ->
|
||||
clearAuthentication?.also { logout.clearAuthentication(clearAuthentication!!) }
|
||||
invalidateHttpSession?.also { logout.invalidateHttpSession(invalidateHttpSession!!) }
|
||||
logoutUrl?.also { logout.logoutUrl(logoutUrl) }
|
||||
logoutRequestMatcher?.also { logout.logoutRequestMatcher(logoutRequestMatcher) }
|
||||
logoutSuccessUrl?.also { logout.logoutSuccessUrl(logoutSuccessUrl) }
|
||||
logoutSuccessHandler?.also { logout.logoutSuccessHandler(logoutSuccessHandler) }
|
||||
deleteCookies?.also { logout.deleteCookies(*deleteCookies!!) }
|
||||
permitAll?.also { logout.permitAll(permitAll!!) }
|
||||
defaultLogoutSuccessHandlerMappings.forEach { (matcher, handler) ->
|
||||
logout.defaultLogoutSuccessHandlerFor(handler, matcher)
|
||||
}
|
||||
logoutHandlers.forEach { logoutHandler ->
|
||||
logout.addLogoutHandler(logoutHandler)
|
||||
}
|
||||
if (disabled) {
|
||||
logout.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
/*
|
||||
* Copyright 2002-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.
|
||||
*/
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.web.servlet.oauth2.client.AuthorizationCodeGrantDsl
|
||||
import org.springframework.security.config.web.servlet.oauth2.login.AuthorizationEndpointDsl
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2ClientConfigurer
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] OAuth 2.0 client support using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property clientRegistrationRepository the repository of client registrations.
|
||||
* @property authorizedClientRepository the repository for authorized client(s).
|
||||
* @property authorizedClientService the service for authorized client(s).
|
||||
*/
|
||||
class OAuth2ClientDsl {
|
||||
var clientRegistrationRepository: ClientRegistrationRepository? = null
|
||||
var authorizedClientRepository: OAuth2AuthorizedClientRepository? = null
|
||||
var authorizedClientService: OAuth2AuthorizedClientService? = null
|
||||
|
||||
private var authorizationCodeGrant: ((OAuth2ClientConfigurer<HttpSecurity>.AuthorizationCodeGrantConfigurer) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* Configures the OAuth 2.0 Authorization Code Grant.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2Client {
|
||||
* authorizationCodeGrant {
|
||||
* authorizationRequestResolver = getAuthorizationRequestResolver()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param authorizationCodeGrantConfig custom configurations to configure the authorization
|
||||
* code grant
|
||||
* @see [AuthorizationEndpointDsl]
|
||||
*/
|
||||
fun authorizationCodeGrant(authorizationCodeGrantConfig: AuthorizationCodeGrantDsl.() -> Unit) {
|
||||
this.authorizationCodeGrant = AuthorizationCodeGrantDsl().apply(authorizationCodeGrantConfig).get()
|
||||
}
|
||||
|
||||
internal fun get(): (OAuth2ClientConfigurer<HttpSecurity>) -> Unit {
|
||||
return { oauth2Client ->
|
||||
clientRegistrationRepository?.also { oauth2Client.clientRegistrationRepository(clientRegistrationRepository) }
|
||||
authorizedClientRepository?.also { oauth2Client.authorizedClientRepository(authorizedClientRepository) }
|
||||
authorizedClientService?.also { oauth2Client.authorizedClientService(authorizedClientService) }
|
||||
authorizationCodeGrant?.also { oauth2Client.authorizationCodeGrant(authorizationCodeGrant) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.web.servlet.oauth2.login.AuthorizationEndpointDsl
|
||||
import org.springframework.security.config.web.servlet.oauth2.login.RedirectionEndpointDsl
|
||||
import org.springframework.security.config.web.servlet.oauth2.login.TokenEndpointDsl
|
||||
import org.springframework.security.config.web.servlet.oauth2.login.UserInfoEndpointDsl
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] OAuth 2.0 login using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property clientRegistrationRepository the repository of client registrations.
|
||||
* @property authorizedClientRepository the repository for authorized client(s).
|
||||
* @property authorizedClientService the service for authorized client(s).
|
||||
* @property loginPage the login page to redirect to if authentication is required (i.e.
|
||||
* "/login")
|
||||
* @property authenticationSuccessHandler the [AuthenticationSuccessHandler] used after
|
||||
* authentication success
|
||||
* @property authenticationFailureHandler the [AuthenticationFailureHandler] used after
|
||||
* authentication success
|
||||
* @property failureUrl the URL to send users if authentication fails
|
||||
* @property loginProcessingUrl the URL to validate the credentials
|
||||
* @property permitAll whether to grant access to the urls for [failureUrl] as well as
|
||||
* for the [HttpSecurityBuilder], the [loginPage] and [loginProcessingUrl] for every user
|
||||
*/
|
||||
class OAuth2LoginDsl {
|
||||
var clientRegistrationRepository: ClientRegistrationRepository? = null
|
||||
var authorizedClientRepository: OAuth2AuthorizedClientRepository? = null
|
||||
var authorizedClientService: OAuth2AuthorizedClientService? = null
|
||||
var loginPage: String? = null
|
||||
var authenticationSuccessHandler: AuthenticationSuccessHandler? = null
|
||||
var authenticationFailureHandler: AuthenticationFailureHandler? = null
|
||||
var failureUrl: String? = null
|
||||
var loginProcessingUrl: String? = null
|
||||
var permitAll: Boolean? = null
|
||||
|
||||
private var defaultSuccessUrlOption: Pair<String, Boolean>? = null
|
||||
private var authorizationEndpoint: ((OAuth2LoginConfigurer<HttpSecurity>.AuthorizationEndpointConfig) -> Unit)? = null
|
||||
private var tokenEndpoint: ((OAuth2LoginConfigurer<HttpSecurity>.TokenEndpointConfig) -> Unit)? = null
|
||||
private var redirectionEndpoint: ((OAuth2LoginConfigurer<HttpSecurity>.RedirectionEndpointConfig) -> Unit)? = null
|
||||
private var userInfoEndpoint: ((OAuth2LoginConfigurer<HttpSecurity>.UserInfoEndpointConfig) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* Grants access to the urls for [failureUrl] as well as for the [HttpSecurityBuilder], the
|
||||
* [loginPage] and [loginProcessingUrl] for every user.
|
||||
*/
|
||||
fun permitAll() {
|
||||
permitAll = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies where users will be redirected after authenticating successfully if
|
||||
* they have not visited a secured page prior to authenticating or [alwaysUse]
|
||||
* is true.
|
||||
*
|
||||
* @param defaultSuccessUrl the default success url
|
||||
* @param alwaysUse true if the [defaultSuccessUrl] should be used after
|
||||
* authentication despite if a protected page had been previously visited
|
||||
*/
|
||||
fun defaultSuccessUrl(defaultSuccessUrl: String, alwaysUse: Boolean) {
|
||||
defaultSuccessUrlOption = Pair(defaultSuccessUrl, alwaysUse)
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Authorization Server's Authorization Endpoint.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2Login {
|
||||
* authorizationEndpoint {
|
||||
* baseUri = "/auth"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param authorizationEndpointConfig custom configurations to configure the authorization
|
||||
* endpoint
|
||||
* @see [AuthorizationEndpointDsl]
|
||||
*/
|
||||
fun authorizationEndpoint(authorizationEndpointConfig: AuthorizationEndpointDsl.() -> Unit) {
|
||||
this.authorizationEndpoint = AuthorizationEndpointDsl().apply(authorizationEndpointConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Authorization Server's Token Endpoint.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2Login {
|
||||
* tokenEndpoint {
|
||||
* accessTokenResponseClient = getAccessTokenResponseClient()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param tokenEndpointConfig custom configurations to configure the token
|
||||
* endpoint
|
||||
* @see [TokenEndpointDsl]
|
||||
*/
|
||||
fun tokenEndpoint(tokenEndpointConfig: TokenEndpointDsl.() -> Unit) {
|
||||
this.tokenEndpoint = TokenEndpointDsl().apply(tokenEndpointConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Authorization Server's Redirection Endpoint.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2Login {
|
||||
* redirectionEndpoint {
|
||||
* baseUri = "/home"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param redirectionEndpointConfig custom configurations to configure the redirection
|
||||
* endpoint
|
||||
* @see [RedirectionEndpointDsl]
|
||||
*/
|
||||
fun redirectionEndpoint(redirectionEndpointConfig: RedirectionEndpointDsl.() -> Unit) {
|
||||
this.redirectionEndpoint = RedirectionEndpointDsl().apply(redirectionEndpointConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Authorization Server's UserInfo Endpoint.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2Login {
|
||||
* userInfoEndpoint {
|
||||
* userService = getUserService()
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param userInfoEndpointConfig custom configurations to configure the user info
|
||||
* endpoint
|
||||
* @see [UserInfoEndpointDsl]
|
||||
*/
|
||||
fun userInfoEndpoint(userInfoEndpointConfig: UserInfoEndpointDsl.() -> Unit) {
|
||||
this.userInfoEndpoint = UserInfoEndpointDsl().apply(userInfoEndpointConfig).get()
|
||||
}
|
||||
|
||||
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>) -> Unit {
|
||||
return { oauth2Login ->
|
||||
clientRegistrationRepository?.also { oauth2Login.clientRegistrationRepository(clientRegistrationRepository) }
|
||||
authorizedClientRepository?.also { oauth2Login.authorizedClientRepository(authorizedClientRepository) }
|
||||
authorizedClientService?.also { oauth2Login.authorizedClientService(authorizedClientService) }
|
||||
loginPage?.also { oauth2Login.loginPage(loginPage) }
|
||||
failureUrl?.also { oauth2Login.failureUrl(failureUrl) }
|
||||
loginProcessingUrl?.also { oauth2Login.loginProcessingUrl(loginProcessingUrl) }
|
||||
permitAll?.also { oauth2Login.permitAll(permitAll!!) }
|
||||
defaultSuccessUrlOption?.also {
|
||||
oauth2Login.defaultSuccessUrl(defaultSuccessUrlOption!!.first, defaultSuccessUrlOption!!.second)
|
||||
}
|
||||
authenticationSuccessHandler?.also { oauth2Login.successHandler(authenticationSuccessHandler) }
|
||||
authenticationFailureHandler?.also { oauth2Login.failureHandler(authenticationFailureHandler) }
|
||||
authorizationEndpoint?.also { oauth2Login.authorizationEndpoint(authorizationEndpoint) }
|
||||
tokenEndpoint?.also { oauth2Login.tokenEndpoint(tokenEndpoint) }
|
||||
redirectionEndpoint?.also { oauth2Login.redirectionEndpoint(redirectionEndpoint) }
|
||||
userInfoEndpoint?.also { oauth2Login.userInfoEndpoint(userInfoEndpoint) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.web.servlet.oauth2.resourceserver.JwtDsl
|
||||
import org.springframework.security.config.web.servlet.oauth2.resourceserver.OpaqueTokenDsl
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer
|
||||
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] OAuth 2.0 resource server support using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property accessDeniedHandler the [AccessDeniedHandler] to use for requests authenticating
|
||||
* with <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>s.
|
||||
* @property authenticationEntryPoint the [AuthenticationEntryPoint] to use for requests authenticating
|
||||
* with <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>s.
|
||||
* @property bearerTokenResolver the [BearerTokenResolver] to use for requests authenticating
|
||||
* with <a href="https://tools.ietf.org/html/rfc6750#section-1.2" target="_blank">Bearer Token</a>s.
|
||||
*/
|
||||
class OAuth2ResourceServerDsl {
|
||||
var accessDeniedHandler: AccessDeniedHandler? = null
|
||||
var authenticationEntryPoint: AuthenticationEntryPoint? = null
|
||||
var bearerTokenResolver: BearerTokenResolver? = null
|
||||
|
||||
private var jwt: ((OAuth2ResourceServerConfigurer<HttpSecurity>.JwtConfigurer) -> Unit)? = null
|
||||
private var opaqueToken: ((OAuth2ResourceServerConfigurer<HttpSecurity>.OpaqueTokenConfigurer) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* Enables JWT-encoded bearer token support.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2ResourceServer {
|
||||
* jwt {
|
||||
* jwkSetUri = "https://example.com/oauth2/jwk"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param jwtConfig custom configurations to configure JWT resource server support
|
||||
* @see [JwtDsl]
|
||||
*/
|
||||
fun jwt(jwtConfig: JwtDsl.() -> Unit) {
|
||||
this.jwt = JwtDsl().apply(jwtConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables opaque token support.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* oauth2ResourceServer {
|
||||
* opaqueToken { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param opaqueTokenConfig custom configurations to configure opaque token resource server support
|
||||
* @see [OpaqueTokenDsl]
|
||||
*/
|
||||
fun opaqueToken(opaqueTokenConfig: OpaqueTokenDsl.() -> Unit) {
|
||||
this.opaqueToken = OpaqueTokenDsl().apply(opaqueTokenConfig).get()
|
||||
}
|
||||
|
||||
internal fun get(): (OAuth2ResourceServerConfigurer<HttpSecurity>) -> Unit {
|
||||
return { oauth2ResourceServer ->
|
||||
accessDeniedHandler?.also { oauth2ResourceServer.accessDeniedHandler(accessDeniedHandler) }
|
||||
authenticationEntryPoint?.also { oauth2ResourceServer.authenticationEntryPoint(authenticationEntryPoint) }
|
||||
bearerTokenResolver?.also { oauth2ResourceServer.bearerTokenResolver(bearerTokenResolver) }
|
||||
jwt?.also { oauth2ResourceServer.jwt(jwt) }
|
||||
opaqueToken?.also { oauth2ResourceServer.opaqueToken(opaqueToken) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.PortMapperConfigurer
|
||||
import org.springframework.security.web.PortMapper
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure a [PortMapper] for [HttpSecurity] using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property portMapper allows specifying the [PortMapper] instance.
|
||||
*/
|
||||
class PortMapperDsl {
|
||||
private val mappings = mutableListOf<Pair<Int, Int>>()
|
||||
|
||||
var portMapper: PortMapper? = null
|
||||
|
||||
/**
|
||||
* Adds a mapping to the port mapper.
|
||||
*
|
||||
* @param fromPort the HTTP port number to map from
|
||||
* @param toPort the HTTPS port number to map to
|
||||
*/
|
||||
fun map(fromPort: Int, toPort: Int) {
|
||||
mappings.add(Pair(fromPort, toPort))
|
||||
}
|
||||
|
||||
internal fun get(): (PortMapperConfigurer<HttpSecurity>) -> Unit {
|
||||
return { portMapperConfig ->
|
||||
portMapper?.also {
|
||||
portMapperConfig.portMapper(portMapper)
|
||||
}
|
||||
this.mappings.forEach {
|
||||
portMapperConfig.http(it.first).mapsTo(it.second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.RequestCacheConfigurer
|
||||
import org.springframework.security.web.savedrequest.RequestCache
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to enable request caching for [HttpSecurity] using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property requestCache allows explicit configuration of the [RequestCache] to be used
|
||||
*/
|
||||
class RequestCacheDsl {
|
||||
var requestCache: RequestCache? = null
|
||||
|
||||
internal fun get(): (RequestCacheConfigurer<HttpSecurity>) -> Unit {
|
||||
return { requestCacheConfig ->
|
||||
requestCache?.also {
|
||||
requestCacheConfig.requestCache(requestCache)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.ChannelSecurityConfigurer
|
||||
import org.springframework.security.web.access.channel.ChannelDecisionManagerImpl
|
||||
import org.springframework.security.web.access.channel.ChannelProcessor
|
||||
import org.springframework.security.web.util.matcher.AnyRequestMatcher
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
import org.springframework.util.ClassUtils
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] channel security using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property channelProcessors the [ChannelProcessor] instances to use in
|
||||
* [ChannelDecisionManagerImpl]
|
||||
*/
|
||||
class RequiresChannelDsl : AbstractRequestMatcherDsl() {
|
||||
private val channelSecurityRules = mutableListOf<AuthorizationRule>()
|
||||
|
||||
private val HANDLER_MAPPING_INTROSPECTOR = "org.springframework.web.servlet.handler.HandlerMappingIntrospector"
|
||||
private val MVC_PRESENT = ClassUtils.isPresent(
|
||||
HANDLER_MAPPING_INTROSPECTOR,
|
||||
RequiresChannelDsl::class.java.classLoader)
|
||||
|
||||
var channelProcessors: List<ChannelProcessor>? = null
|
||||
|
||||
/**
|
||||
* Adds a channel security rule.
|
||||
*
|
||||
* @param matches the [RequestMatcher] to match incoming requests against
|
||||
* @param attribute the configuration attribute to secure the matching request
|
||||
* (i.e. "REQUIRES_SECURE_CHANNEL")
|
||||
*/
|
||||
fun secure(matches: RequestMatcher = AnyRequestMatcher.INSTANCE,
|
||||
attribute: String = "REQUIRES_SECURE_CHANNEL") {
|
||||
channelSecurityRules.add(MatcherAuthorizationRule(matches, attribute))
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param attribute the configuration attribute to secure the matching request
|
||||
* (i.e. "REQUIRES_SECURE_CHANNEL")
|
||||
*/
|
||||
fun secure(pattern: String, attribute: String = "REQUIRES_SECURE_CHANNEL") {
|
||||
if (MVC_PRESENT) {
|
||||
channelSecurityRules.add(PatternAuthorizationRule(pattern, PatternType.MVC, null, attribute))
|
||||
} else {
|
||||
channelSecurityRules.add(PatternAuthorizationRule(pattern, PatternType.ANT, null, attribute))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a request authorization rule for an endpoint matching the provided
|
||||
* pattern.
|
||||
* If Spring MVC is not an the classpath, it will use an ant matcher.
|
||||
* If Spring MVC is on the classpath, it will use an MVC matcher.
|
||||
* The MVC will use the same rules that Spring MVC uses for matching.
|
||||
* For example, often times a mapping of the path "/path" will match on
|
||||
* "/path", "/path/", "/path.html", etc.
|
||||
* If the current request will not be processed by Spring MVC, a reasonable default
|
||||
* using the pattern as an ant pattern will be used.
|
||||
*
|
||||
* @param pattern the pattern to match incoming requests against.
|
||||
* @param servletPath the servlet path to match incoming requests against. This
|
||||
* only applies when using an MVC pattern matcher.
|
||||
* @param attribute the configuration attribute to secure the matching request
|
||||
* (i.e. "REQUIRES_SECURE_CHANNEL")
|
||||
*/
|
||||
fun secure(pattern: String, servletPath: String, attribute: String = "REQUIRES_SECURE_CHANNEL") {
|
||||
if (MVC_PRESENT) {
|
||||
channelSecurityRules.add(PatternAuthorizationRule(pattern, PatternType.MVC, servletPath, attribute))
|
||||
} else {
|
||||
channelSecurityRules.add(PatternAuthorizationRule(pattern, PatternType.ANT, servletPath, attribute))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify channel security is active.
|
||||
*/
|
||||
val requiresSecure = "REQUIRES_SECURE_CHANNEL"
|
||||
|
||||
/**
|
||||
* Specify channel security is inactive.
|
||||
*/
|
||||
val requiresInsecure = "REQUIRES_INSECURE_CHANNEL"
|
||||
|
||||
internal fun get(): (ChannelSecurityConfigurer<HttpSecurity>.ChannelRequestMatcherRegistry) -> Unit {
|
||||
return { channelSecurity ->
|
||||
channelProcessors?.also { channelSecurity.channelProcessors(channelProcessors) }
|
||||
channelSecurityRules.forEach { rule ->
|
||||
when (rule) {
|
||||
is MatcherAuthorizationRule -> channelSecurity.requestMatchers(rule.matcher).requires(rule.rule)
|
||||
is PatternAuthorizationRule -> {
|
||||
when (rule.patternType) {
|
||||
PatternType.ANT -> channelSecurity.antMatchers(rule.pattern).requires(rule.rule)
|
||||
PatternType.MVC -> {
|
||||
val mvcMatchersRequiresChannel = channelSecurity.mvcMatchers(rule.pattern)
|
||||
rule.servletPath?.also { mvcMatchersRequiresChannel.servletPath(rule.servletPath) }
|
||||
mvcMatchersRequiresChannel.requires(rule.rule)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LoginConfigurer
|
||||
import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.AuthenticationSuccessHandler
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] SAML2 login using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property relyingPartyRegistrationRepository the [RelyingPartyRegistrationRepository] of relying parties,
|
||||
* each party representing a service provider, SP and this host, and identity provider, IDP pair that
|
||||
* communicate with each other.
|
||||
* @property loginPage the login page to redirect to if authentication is required (i.e.
|
||||
* "/login")
|
||||
* @property authenticationSuccessHandler the [AuthenticationSuccessHandler] used after
|
||||
* authentication success
|
||||
* @property authenticationFailureHandler the [AuthenticationFailureHandler] used after
|
||||
* authentication success
|
||||
* @property failureUrl the URL to send users if authentication fails
|
||||
* @property loginProcessingUrl the URL to validate the credentials
|
||||
* @property permitAll whether to grant access to the urls for [failureUrl] as well as
|
||||
* for the [HttpSecurityBuilder], the [loginPage] and [loginProcessingUrl] for every user
|
||||
*/
|
||||
class Saml2Dsl {
|
||||
var relyingPartyRegistrationRepository: RelyingPartyRegistrationRepository? = null
|
||||
var loginPage: String? = null
|
||||
var authenticationSuccessHandler: AuthenticationSuccessHandler? = null
|
||||
var authenticationFailureHandler: AuthenticationFailureHandler? = null
|
||||
var failureUrl: String? = null
|
||||
var loginProcessingUrl: String? = null
|
||||
var permitAll: Boolean? = null
|
||||
|
||||
private var defaultSuccessUrlOption: Pair<String, Boolean>? = null
|
||||
|
||||
/**
|
||||
* Grants access to the urls for [failureUrl] as well as for the [HttpSecurityBuilder], the
|
||||
* [loginPage] and [loginProcessingUrl] for every user.
|
||||
*/
|
||||
fun permitAll() {
|
||||
permitAll = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies where users will be redirected after authenticating successfully if
|
||||
* they have not visited a secured page prior to authenticating or [alwaysUse]
|
||||
* is true.
|
||||
*
|
||||
* @param defaultSuccessUrl the default success url
|
||||
* @param alwaysUse true if the [defaultSuccessUrl] should be used after
|
||||
* authentication despite if a protected page had been previously visited
|
||||
*/
|
||||
fun defaultSuccessUrl(defaultSuccessUrl: String, alwaysUse: Boolean) {
|
||||
defaultSuccessUrlOption = Pair(defaultSuccessUrl, alwaysUse)
|
||||
}
|
||||
|
||||
internal fun get(): (Saml2LoginConfigurer<HttpSecurity>) -> Unit {
|
||||
return { saml2Login ->
|
||||
relyingPartyRegistrationRepository?.also { saml2Login.relyingPartyRegistrationRepository(relyingPartyRegistrationRepository) }
|
||||
loginPage?.also { saml2Login.loginPage(loginPage) }
|
||||
failureUrl?.also { saml2Login.failureUrl(failureUrl) }
|
||||
loginProcessingUrl?.also { saml2Login.loginProcessingUrl(loginProcessingUrl) }
|
||||
permitAll?.also { saml2Login.permitAll(permitAll!!) }
|
||||
defaultSuccessUrlOption?.also {
|
||||
saml2Login.defaultSuccessUrl(defaultSuccessUrlOption!!.first, defaultSuccessUrlOption!!.second)
|
||||
}
|
||||
authenticationSuccessHandler?.also { saml2Login.successHandler(authenticationSuccessHandler) }
|
||||
authenticationFailureHandler?.also { saml2Login.failureHandler(authenticationFailureHandler) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.web.servlet.session.SessionConcurrencyDsl
|
||||
import org.springframework.security.config.web.servlet.session.SessionFixationDsl
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
|
||||
import org.springframework.security.config.http.SessionCreationPolicy
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy
|
||||
import org.springframework.security.web.session.InvalidSessionStrategy
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] session management using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
*/
|
||||
class SessionManagementDsl {
|
||||
var invalidSessionUrl: String? = null
|
||||
var invalidSessionStrategy: InvalidSessionStrategy? = null
|
||||
var sessionAuthenticationErrorUrl: String? = null
|
||||
var sessionAuthenticationFailureHandler: AuthenticationFailureHandler? = null
|
||||
var enableSessionUrlRewriting: Boolean? = null
|
||||
var sessionCreationPolicy: SessionCreationPolicy? = null
|
||||
var sessionAuthenticationStrategy: SessionAuthenticationStrategy? = null
|
||||
private var sessionFixation: ((SessionManagementConfigurer<HttpSecurity>.SessionFixationConfigurer) -> Unit)? = null
|
||||
private var sessionConcurrency: ((SessionManagementConfigurer<HttpSecurity>.ConcurrencyControlConfigurer) -> Unit)? = null
|
||||
|
||||
/**
|
||||
* Enables session fixation protection.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* sessionManagement {
|
||||
* sessionFixation { }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param sessionFixationConfig custom configurations to configure session fixation
|
||||
* protection
|
||||
* @see [SessionFixationDsl]
|
||||
*/
|
||||
fun sessionFixation(sessionFixationConfig: SessionFixationDsl.() -> Unit) {
|
||||
this.sessionFixation = SessionFixationDsl().apply(sessionFixationConfig).get()
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls the behaviour of multiple sessions for a user.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```
|
||||
* @EnableWebSecurity
|
||||
* class SecurityConfig : WebSecurityConfigurerAdapter() {
|
||||
*
|
||||
* override fun configure(http: HttpSecurity) {
|
||||
* httpSecurity(http) {
|
||||
* sessionManagement {
|
||||
* sessionConcurrency {
|
||||
* maximumSessions = 1
|
||||
* maxSessionsPreventsLogin = true
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @param sessionConcurrencyConfig custom configurations to configure concurrency
|
||||
* control
|
||||
* @see [SessionConcurrencyDsl]
|
||||
*/
|
||||
fun sessionConcurrency(sessionConcurrencyConfig: SessionConcurrencyDsl.() -> Unit) {
|
||||
this.sessionConcurrency = SessionConcurrencyDsl().apply(sessionConcurrencyConfig).get()
|
||||
}
|
||||
|
||||
internal fun get(): (SessionManagementConfigurer<HttpSecurity>) -> Unit {
|
||||
return { sessionManagement ->
|
||||
invalidSessionUrl?.also { sessionManagement.invalidSessionUrl(invalidSessionUrl) }
|
||||
invalidSessionStrategy?.also { sessionManagement.invalidSessionStrategy(invalidSessionStrategy) }
|
||||
sessionAuthenticationErrorUrl?.also { sessionManagement.sessionAuthenticationErrorUrl(sessionAuthenticationErrorUrl) }
|
||||
sessionAuthenticationFailureHandler?.also { sessionManagement.sessionAuthenticationFailureHandler(sessionAuthenticationFailureHandler) }
|
||||
enableSessionUrlRewriting?.also { sessionManagement.enableSessionUrlRewriting(enableSessionUrlRewriting!!) }
|
||||
sessionCreationPolicy?.also { sessionManagement.sessionCreationPolicy(sessionCreationPolicy) }
|
||||
sessionAuthenticationStrategy?.also { sessionManagement.sessionAuthenticationStrategy(sessionAuthenticationStrategy) }
|
||||
sessionFixation?.also { sessionManagement.sessionFixation(sessionFixation) }
|
||||
sessionConcurrency?.also { sessionManagement.sessionConcurrency(sessionConcurrency) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.X509Configurer
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper
|
||||
import org.springframework.security.core.userdetails.UserDetailsService
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken
|
||||
import org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails
|
||||
import org.springframework.security.web.authentication.preauth.x509.X509AuthenticationFilter
|
||||
import org.springframework.security.web.authentication.preauth.x509.X509PrincipalExtractor
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] X509 based pre authentication
|
||||
* using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property x509AuthenticationFilter the entire [X509AuthenticationFilter]. If
|
||||
* this is specified, the properties on [X509Configurer] will not be populated
|
||||
* on the {@link X509AuthenticationFilter}.
|
||||
* @property x509PrincipalExtractor the [X509PrincipalExtractor]
|
||||
* @property authenticationDetailsSource the [X509PrincipalExtractor]
|
||||
* @property userDetailsService shortcut for invoking
|
||||
* [authenticationUserDetailsService] with a [UserDetailsByNameServiceWrapper]
|
||||
* @property authenticationUserDetailsService the [AuthenticationUserDetailsService] to use
|
||||
* @property subjectPrincipalRegex the regex to extract the principal from the certificate
|
||||
*/
|
||||
class X509Dsl {
|
||||
var x509AuthenticationFilter: X509AuthenticationFilter? = null
|
||||
var x509PrincipalExtractor: X509PrincipalExtractor? = null
|
||||
var authenticationDetailsSource: AuthenticationDetailsSource<HttpServletRequest, PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails>? = null
|
||||
var userDetailsService: UserDetailsService? = null
|
||||
var authenticationUserDetailsService: AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken>? = null
|
||||
var subjectPrincipalRegex: String? = null
|
||||
|
||||
internal fun get(): (X509Configurer<HttpSecurity>) -> Unit {
|
||||
return { x509 ->
|
||||
x509AuthenticationFilter?.also { x509.x509AuthenticationFilter(x509AuthenticationFilter) }
|
||||
x509PrincipalExtractor?.also { x509.x509PrincipalExtractor(x509PrincipalExtractor) }
|
||||
authenticationDetailsSource?.also { x509.authenticationDetailsSource(authenticationDetailsSource) }
|
||||
userDetailsService?.also { x509.userDetailsService(userDetailsService) }
|
||||
authenticationUserDetailsService?.also { x509.authenticationUserDetailsService(authenticationUserDetailsService) }
|
||||
subjectPrincipalRegex?.also { x509.subjectPrincipalRegex(subjectPrincipalRegex) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] cache control headers using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
*/
|
||||
class CacheControlDsl {
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable cache control headers.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.CacheControlConfig) -> Unit {
|
||||
return { cacheControl ->
|
||||
if (disabled) {
|
||||
cacheControl.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] Content-Security-Policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property policyDirectives the security policy directive(s) to be used in the response header.
|
||||
* @property reportOnly includes the Content-Security-Policy-Report-Only header in the response.
|
||||
*/
|
||||
class ContentSecurityPolicyDsl {
|
||||
var policyDirectives: String? = null
|
||||
var reportOnly: Boolean? = null
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.ContentSecurityPolicyConfig) -> Unit {
|
||||
return { contentSecurityPolicy ->
|
||||
policyDirectives?.also {
|
||||
contentSecurityPolicy.policyDirectives(policyDirectives)
|
||||
}
|
||||
reportOnly?.also {
|
||||
if (reportOnly!!) {
|
||||
contentSecurityPolicy.reportOnly()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure [HttpSecurity] X-Content-Type-Options header using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
*/
|
||||
class ContentTypeOptionsDsl {
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable the X-Content-Type-Options header.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.ContentTypeOptionsConfig) -> Unit {
|
||||
return { contentTypeOptions ->
|
||||
if (disabled) {
|
||||
contentTypeOptions.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] X-Frame-Options header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property sameOrigin allow any request that comes from the same origin to frame this
|
||||
* application.
|
||||
* @property deny deny framing any content from this application.
|
||||
*/
|
||||
class FrameOptionsDsl {
|
||||
var sameOrigin: Boolean? = null
|
||||
var deny: Boolean? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable the X-Frame-Options header.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.FrameOptionsConfig) -> Unit {
|
||||
return { frameOptions ->
|
||||
sameOrigin?.also {
|
||||
if (sameOrigin!!) {
|
||||
frameOptions.sameOrigin()
|
||||
}
|
||||
}
|
||||
deny?.also {
|
||||
if (deny!!) {
|
||||
frameOptions.deny()
|
||||
}
|
||||
}
|
||||
if (disabled) {
|
||||
frameOptions.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] HTTP Public Key Pinning header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property pins the value for the pin- directive of the Public-Key-Pins header.
|
||||
* @property maxAgeInSeconds the value (in seconds) for the max-age directive of the
|
||||
* Public-Key-Pins header.
|
||||
* @property includeSubDomains if true, the pinning policy applies to this pinned host
|
||||
* as well as any subdomains of the host's domain name.
|
||||
* @property reportOnly if true, the browser should not terminate the connection with
|
||||
* the server.
|
||||
* @property reportUri the URI to which the browser should report pin validation failures.
|
||||
*/
|
||||
class HttpPublicKeyPinningDsl {
|
||||
var pins: Map<String, String>? = null
|
||||
var maxAgeInSeconds: Long? = null
|
||||
var includeSubDomains: Boolean? = null
|
||||
var reportOnly: Boolean? = null
|
||||
var reportUri: String? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable the HTTP Public Key Pinning header.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.HpkpConfig) -> Unit {
|
||||
return { hpkp ->
|
||||
pins?.also {
|
||||
hpkp.withPins(pins)
|
||||
}
|
||||
maxAgeInSeconds?.also {
|
||||
hpkp.maxAgeInSeconds(maxAgeInSeconds!!)
|
||||
}
|
||||
includeSubDomains?.also {
|
||||
hpkp.includeSubDomains(includeSubDomains!!)
|
||||
}
|
||||
reportOnly?.also {
|
||||
hpkp.reportOnly(reportOnly!!)
|
||||
}
|
||||
reportUri?.also {
|
||||
hpkp.reportUri(reportUri)
|
||||
}
|
||||
if (disabled) {
|
||||
hpkp.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] HTTP Strict Transport Security header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property maxAgeInSeconds the value (in seconds) for the max-age directive of the
|
||||
* Strict-Transport-Security header.
|
||||
* @property requestMatcher the [RequestMatcher] used to determine if the
|
||||
* "Strict-Transport-Security" header should be added. If true the header is added,
|
||||
* else the header is not added.
|
||||
* @property includeSubDomains if true, subdomains should be considered HSTS Hosts too.
|
||||
* @property preload if true, preload will be included in HSTS Header.
|
||||
*/
|
||||
class HttpStrictTransportSecurityDsl {
|
||||
var maxAgeInSeconds: Long? = null
|
||||
var requestMatcher: RequestMatcher? = null
|
||||
var includeSubDomains: Boolean? = null
|
||||
var preload: Boolean? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Disable the HTTP Strict Transport Security header.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.HstsConfig) -> Unit {
|
||||
return { hsts ->
|
||||
maxAgeInSeconds?.also { hsts.maxAgeInSeconds(maxAgeInSeconds!!) }
|
||||
requestMatcher?.also { hsts.requestMatcher(requestMatcher) }
|
||||
includeSubDomains?.also { hsts.includeSubDomains(includeSubDomains!!) }
|
||||
preload?.also { hsts.preload(preload!!) }
|
||||
if (disabled) {
|
||||
hsts.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] referrer policy header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property policy the policy to be used in the response header.
|
||||
*/
|
||||
class ReferrerPolicyDsl {
|
||||
var policy: ReferrerPolicyHeaderWriter.ReferrerPolicy? = null
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.ReferrerPolicyConfig) -> Unit {
|
||||
return { referrerPolicy ->
|
||||
policy?.also {
|
||||
referrerPolicy.policy(policy)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.headers
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the [HttpSecurity] XSS protection header using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property block whether to specify the mode as blocked
|
||||
* @property xssProtectionEnabled if true, the header value will contain a value of 1.
|
||||
* If false, will explicitly disable specify that X-XSS-Protection is disabled.
|
||||
*/
|
||||
class XssProtectionConfigDsl {
|
||||
var block: Boolean? = null
|
||||
var xssProtectionEnabled: Boolean? = null
|
||||
|
||||
private var disabled = false
|
||||
|
||||
/**
|
||||
* Do not include the X-XSS-Protection header in the response.
|
||||
*/
|
||||
fun disable() {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
internal fun get(): (HeadersConfigurer<HttpSecurity>.XXssConfig) -> Unit {
|
||||
return { xssProtection ->
|
||||
block?.also { xssProtection.block(block!!) }
|
||||
xssProtectionEnabled?.also { xssProtection.xssProtectionEnabled(xssProtectionEnabled!!) }
|
||||
|
||||
if (disabled) {
|
||||
xssProtection.disable()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.client
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2ClientConfigurer
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest
|
||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure OAuth 2.0 Authorization Code Grant.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property authorizationRequestResolver the resolver used for resolving [OAuth2AuthorizationRequest]'s.
|
||||
* @property authorizationRequestRepository the repository used for storing [OAuth2AuthorizationRequest]'s.
|
||||
* @property accessTokenResponseClient the client used for requesting the access token credential
|
||||
* from the Token Endpoint.
|
||||
*/
|
||||
class AuthorizationCodeGrantDsl {
|
||||
var authorizationRequestResolver: OAuth2AuthorizationRequestResolver? = null
|
||||
var authorizationRequestRepository: AuthorizationRequestRepository<OAuth2AuthorizationRequest>? = null
|
||||
var accessTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest>? = null
|
||||
|
||||
internal fun get(): (OAuth2ClientConfigurer<HttpSecurity>.AuthorizationCodeGrantConfigurer) -> Unit {
|
||||
return { authorizationCodeGrant ->
|
||||
authorizationRequestResolver?.also { authorizationCodeGrant.authorizationRequestResolver(authorizationRequestResolver) }
|
||||
authorizationRequestRepository?.also { authorizationCodeGrant.authorizationRequestRepository(authorizationRequestRepository) }
|
||||
accessTokenResponseClient?.also { authorizationCodeGrant.accessTokenResponseClient(accessTokenResponseClient) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.login
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
||||
import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the Authorization Server's Authorization Endpoint using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property baseUri the base URI used for authorization requests.
|
||||
* @property authorizationRequestResolver the resolver used for resolving [OAuth2AuthorizationRequest]'s.
|
||||
* @property authorizationRequestRepository the repository used for storing [OAuth2AuthorizationRequest]'s.
|
||||
*/
|
||||
class AuthorizationEndpointDsl {
|
||||
var baseUri: String? = null
|
||||
var authorizationRequestResolver: OAuth2AuthorizationRequestResolver? = null
|
||||
var authorizationRequestRepository: AuthorizationRequestRepository<OAuth2AuthorizationRequest>? = null
|
||||
|
||||
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.AuthorizationEndpointConfig) -> Unit {
|
||||
return { authorizationEndpoint ->
|
||||
baseUri?.also { authorizationEndpoint.baseUri(baseUri) }
|
||||
authorizationRequestResolver?.also { authorizationEndpoint.authorizationRequestResolver(authorizationRequestResolver) }
|
||||
authorizationRequestRepository?.also { authorizationEndpoint.authorizationRequestRepository(authorizationRequestRepository) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.login
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the Authorization Server's Redirection Endpoint using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property baseUri the URI where the authorization response will be processed.
|
||||
*/
|
||||
class RedirectionEndpointDsl {
|
||||
var baseUri: String? = null
|
||||
|
||||
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.RedirectionEndpointConfig) -> Unit {
|
||||
return { redirectionEndpoint ->
|
||||
baseUri?.also { redirectionEndpoint.baseUri(baseUri) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.login
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the Authorization Server's Token Endpoint using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property accessTokenResponseClient the client used for requesting the access token credential
|
||||
* from the Token Endpoint.
|
||||
*/
|
||||
class TokenEndpointDsl {
|
||||
var accessTokenResponseClient: OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest>? = null
|
||||
|
||||
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.TokenEndpointConfig) -> Unit {
|
||||
return { tokenEndpoint ->
|
||||
accessTokenResponseClient?.also { tokenEndpoint.accessTokenResponseClient(accessTokenResponseClient) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.login
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper
|
||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the Authorization Server's UserInfo Endpoint using
|
||||
* idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property userService the OAuth 2.0 service used for obtaining the user attributes of the End-User
|
||||
* from the UserInfo Endpoint.
|
||||
* @property oidcUserService the OpenID Connect 1.0 service used for obtaining the user attributes of the
|
||||
* End-User from the UserInfo Endpoint.
|
||||
* @property userAuthoritiesMapper the [GrantedAuthoritiesMapper] used for mapping [OAuth2User.getAuthorities]
|
||||
*/
|
||||
class UserInfoEndpointDsl {
|
||||
var userService: OAuth2UserService<OAuth2UserRequest, OAuth2User>? = null
|
||||
var oidcUserService: OAuth2UserService<OidcUserRequest, OidcUser>? = null
|
||||
var userAuthoritiesMapper: GrantedAuthoritiesMapper? = null
|
||||
|
||||
private var customUserTypePair: Pair<Class<out OAuth2User>, String>? = null
|
||||
|
||||
/**
|
||||
* Sets a custom [OAuth2User] type and associates it to the provided
|
||||
* client [ClientRegistration.getRegistrationId] registration identifier.
|
||||
*
|
||||
* @param customUserType a custom [OAuth2User] type
|
||||
* @param clientRegistrationId the client registration identifier
|
||||
*/
|
||||
fun customUserType(customUserType: Class<out OAuth2User>, clientRegistrationId: String) {
|
||||
customUserTypePair = Pair(customUserType, clientRegistrationId)
|
||||
}
|
||||
|
||||
internal fun get(): (OAuth2LoginConfigurer<HttpSecurity>.UserInfoEndpointConfig) -> Unit {
|
||||
return { userInfoEndpoint ->
|
||||
userService?.also { userInfoEndpoint.userService(userService) }
|
||||
oidcUserService?.also { userInfoEndpoint.oidcUserService(oidcUserService) }
|
||||
userAuthoritiesMapper?.also { userInfoEndpoint.userAuthoritiesMapper(userAuthoritiesMapper) }
|
||||
customUserTypePair?.also { userInfoEndpoint.customUserType(customUserTypePair!!.first, customUserTypePair!!.second) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.resourceserver
|
||||
|
||||
import org.springframework.core.convert.converter.Converter
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer
|
||||
import org.springframework.security.oauth2.jwt.Jwt
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure JWT Resource Server Support using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property jwtAuthenticationConverter the [Converter] to use for converting a [Jwt] into
|
||||
* an [AbstractAuthenticationToken].
|
||||
* @property jwtDecoder the [JwtDecoder] to use.
|
||||
* @property jwkSetUri configures a [JwtDecoder] using a
|
||||
* <a target="_blank" href="https://tools.ietf.org/html/rfc7517">JSON Web Key (JWK)</a> URL
|
||||
*/
|
||||
class JwtDsl {
|
||||
var jwtAuthenticationConverter: Converter<Jwt, out AbstractAuthenticationToken>? = null
|
||||
var jwtDecoder: JwtDecoder? = null
|
||||
var jwkSetUri: String? = null
|
||||
|
||||
internal fun get(): (OAuth2ResourceServerConfigurer<HttpSecurity>.JwtConfigurer) -> Unit {
|
||||
return { jwt ->
|
||||
jwtAuthenticationConverter?.also { jwt.jwtAuthenticationConverter(jwtAuthenticationConverter) }
|
||||
jwtDecoder?.also { jwt.decoder(jwtDecoder) }
|
||||
jwkSetUri?.also { jwt.jwkSetUri(jwkSetUri) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.oauth2.resourceserver
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer
|
||||
import org.springframework.security.oauth2.server.resource.introspection.OpaqueTokenIntrospector
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure JWT Resource Server Support using idiomatic Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property introspectionUri the URI of the Introspection endpoint.
|
||||
* @property introspector the [OpaqueTokenIntrospector] to use.
|
||||
*/
|
||||
class OpaqueTokenDsl {
|
||||
var introspectionUri: String? = null
|
||||
var introspector: OpaqueTokenIntrospector? = null
|
||||
|
||||
private var clientCredentials: Pair<String, String>? = null
|
||||
|
||||
/**
|
||||
* Configures the credentials for Introspection endpoint.
|
||||
*
|
||||
* @param clientId the clientId part of the credentials.
|
||||
* @param clientSecret the clientSecret part of the credentials.
|
||||
*/
|
||||
fun introspectionClientCredentials(clientId: String, clientSecret: String) {
|
||||
clientCredentials = Pair(clientId, clientSecret)
|
||||
}
|
||||
|
||||
internal fun get(): (OAuth2ResourceServerConfigurer<HttpSecurity>.OpaqueTokenConfigurer) -> Unit {
|
||||
return { opaqueToken ->
|
||||
introspectionUri?.also { opaqueToken.introspectionUri(introspectionUri) }
|
||||
introspector?.also { opaqueToken.introspector(introspector) }
|
||||
clientCredentials?.also { opaqueToken.introspectionClientCredentials(clientCredentials!!.first, clientCredentials!!.second) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.session
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
|
||||
import org.springframework.security.core.session.SessionRegistry
|
||||
import org.springframework.security.web.session.SessionInformationExpiredStrategy
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure the behaviour of multiple sessions using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
* @property maximumSessions controls the maximum number of sessions for a user.
|
||||
* @property expiredUrl the URL to redirect to if a user tries to access a resource and
|
||||
* their session has been expired due to too many sessions for the current user.
|
||||
* @property expiredSessionStrategy determines the behaviour when an expired session
|
||||
* is detected.
|
||||
* @property maxSessionsPreventsLogin if true, prevents a user from authenticating when the
|
||||
* [maximumSessions] has been reached. Otherwise (default), the user who authenticates
|
||||
* is allowed access and an existing user's session is expired.
|
||||
* @property sessionRegistry the [SessionRegistry] implementation used.
|
||||
*
|
||||
*/
|
||||
class SessionConcurrencyDsl {
|
||||
var maximumSessions: Int? = null
|
||||
var expiredUrl: String? = null
|
||||
var expiredSessionStrategy: SessionInformationExpiredStrategy? = null
|
||||
var maxSessionsPreventsLogin: Boolean? = null
|
||||
var sessionRegistry: SessionRegistry? = null
|
||||
|
||||
internal fun get(): (SessionManagementConfigurer<HttpSecurity>.ConcurrencyControlConfigurer) -> Unit {
|
||||
return { sessionConcurrencyControl ->
|
||||
maximumSessions?.also {
|
||||
sessionConcurrencyControl.maximumSessions(maximumSessions!!)
|
||||
}
|
||||
expiredUrl?.also {
|
||||
sessionConcurrencyControl.expiredUrl(expiredUrl)
|
||||
}
|
||||
expiredSessionStrategy?.also {
|
||||
sessionConcurrencyControl.expiredSessionStrategy(expiredSessionStrategy)
|
||||
}
|
||||
maxSessionsPreventsLogin?.also {
|
||||
sessionConcurrencyControl.maxSessionsPreventsLogin(maxSessionsPreventsLogin!!)
|
||||
}
|
||||
sessionRegistry?.also {
|
||||
sessionConcurrencyControl.sessionRegistry(sessionRegistry)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2002-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 org.springframework.security.config.web.servlet.session
|
||||
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer
|
||||
import javax.servlet.http.HttpServletRequest
|
||||
import javax.servlet.http.HttpSession
|
||||
|
||||
/**
|
||||
* A Kotlin DSL to configure session fixation protection using idiomatic
|
||||
* Kotlin code.
|
||||
*
|
||||
* @author Eleftheria Stein
|
||||
* @since 5.3
|
||||
*/
|
||||
class SessionFixationDsl {
|
||||
private var strategy: SessionFixationStrategy? = null
|
||||
|
||||
/**
|
||||
* Specifies that a new session should be created, but the session attributes from
|
||||
* the original [HttpSession] should not be retained.
|
||||
*/
|
||||
fun newSession() {
|
||||
this.strategy = SessionFixationStrategy.NEW
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that a new session should be created and the session attributes from
|
||||
* the original [HttpSession] should be retained.
|
||||
*/
|
||||
fun migrateSession() {
|
||||
this.strategy = SessionFixationStrategy.MIGRATE
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that the Servlet container-provided session fixation protection
|
||||
* should be used. When a session authenticates, the Servlet method
|
||||
* [HttpServletRequest.changeSessionId] is called to change the session ID
|
||||
* and retain all session attributes.
|
||||
*/
|
||||
fun changeSessionId() {
|
||||
this.strategy = SessionFixationStrategy.CHANGE_ID
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that no session fixation protection should be enabled.
|
||||
*/
|
||||
fun none() {
|
||||
this.strategy = SessionFixationStrategy.NONE
|
||||
}
|
||||
|
||||
internal fun get(): (SessionManagementConfigurer<HttpSecurity>.SessionFixationConfigurer) -> Unit {
|
||||
return { sessionFixation ->
|
||||
strategy?.also {
|
||||
when (strategy) {
|
||||
SessionFixationStrategy.NEW -> sessionFixation.newSession()
|
||||
SessionFixationStrategy.MIGRATE -> sessionFixation.migrateSession()
|
||||
SessionFixationStrategy.CHANGE_ID -> sessionFixation.changeSessionId()
|
||||
SessionFixationStrategy.NONE -> sessionFixation.none()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum class SessionFixationStrategy {
|
||||
NEW, MIGRATE, CHANGE_ID, NONE
|
||||
}
|
||||
Reference in New Issue
Block a user