Compare commits
9 Commits
master
...
feature/in
| Author | SHA1 | Date |
|---|---|---|
|
|
27ba862dde | |
|
|
78e6d09bce | |
|
|
75f7f05f82 | |
|
|
624c905af8 | |
|
|
2fc996f8c5 | |
|
|
607c7b3a01 | |
|
|
f941ad4359 | |
|
|
f8f1ca5297 | |
|
|
3b7c40b74f |
19
build.gradle
19
build.gradle
|
|
@ -20,7 +20,7 @@ buildscript {
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath "de.undercouch:gradle-download-task:${project.gradleDownloadTaskVersion}"
|
classpath "de.undercouch:gradle-download-task:${project.gradleDownloadTaskVersion}"
|
||||||
classpath "org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}"
|
classpath "org.springframework.boot:spring-boot-gradle-plugin:${project.springBootVersion}"
|
||||||
classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:${project.jibVersion}"
|
classpath "com.google.cloud.tools:jib-gradle-plugin:${project.jibVersion}"
|
||||||
classpath "io.freefair.gradle:maven-plugin:${project.gradleMavenPluginVersion}"
|
classpath "io.freefair.gradle:maven-plugin:${project.gradleMavenPluginVersion}"
|
||||||
classpath "io.freefair.gradle:lombok-plugin:${project.gradleLombokPluginVersion}"
|
classpath "io.freefair.gradle:lombok-plugin:${project.gradleLombokPluginVersion}"
|
||||||
}
|
}
|
||||||
|
|
@ -70,8 +70,21 @@ apply from: rootProject.file("gradle/springboot.gradle")
|
||||||
apply from: rootProject.file("gradle/dockerjib.gradle")
|
apply from: rootProject.file("gradle/dockerjib.gradle")
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Other CAS dependencies/modules may be listed here...
|
// Module dependencies
|
||||||
// implementation "org.apereo.cas:cas-server-support-json-service-registry:${casServerVersion}"
|
compile "org.apereo.cas:cas-server-support-ldap:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-reports:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-yaml-service-registry:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-oauth-webflow:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-redis-ticket-registry:${project.'cas.version'}"
|
||||||
|
|
||||||
|
// Api dependencies
|
||||||
|
compile "org.apereo.cas:cas-server-core-util-api:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-core-api-services:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-core-services-api:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-core-authentication-api:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-oauth-api:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-oauth-core-api:${project.'cas.version'}"
|
||||||
|
compile "org.apereo.cas:cas-server-support-oauth-services:${project.'cas.version'}"
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.findByName("jibDockerBuild")
|
tasks.findByName("jibDockerBuild")
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# Versions
|
# Versions
|
||||||
cas.version=6.2.0-SNAPSHOT
|
cas.version=6.2.0-RC2
|
||||||
springBootVersion=2.2.5.RELEASE
|
springBootVersion=2.2.5.RELEASE
|
||||||
|
|
||||||
# Use -jetty, -undertow to other containers
|
# Use -jetty, -undertow to other containers
|
||||||
|
|
@ -7,13 +7,13 @@ springBootVersion=2.2.5.RELEASE
|
||||||
appServer=-tomcat
|
appServer=-tomcat
|
||||||
executable=false
|
executable=false
|
||||||
|
|
||||||
tomcatVersion=9.0.33
|
tomcatVersion=9.0.34
|
||||||
|
|
||||||
group=org.apereo.cas
|
group=org.apereo.cas
|
||||||
sourceCompatibility=11
|
sourceCompatibility=11
|
||||||
targetCompatibility=11
|
targetCompatibility=11
|
||||||
|
|
||||||
jibVersion=2.1.0
|
jibVersion=2.2.0
|
||||||
|
|
||||||
# Location of the downloaded CAS shell JAR
|
# Location of the downloaded CAS shell JAR
|
||||||
shellDir=build/libs
|
shellDir=build/libs
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,9 @@ project.ext."tomcatDirectory" = tomcatDirectory
|
||||||
|
|
||||||
def explodedDir = "${buildDir}/cas"
|
def explodedDir = "${buildDir}/cas"
|
||||||
def explodedResourcesDir = "${buildDir}/cas-resources"
|
def explodedResourcesDir = "${buildDir}/cas-resources"
|
||||||
def resourceJarName = "cas-server-webapp-resources"
|
|
||||||
|
def resourcesJarName = "cas-server-webapp-resources"
|
||||||
|
def templateViewsJarName = "cas-server-support-thymeleaf"
|
||||||
|
|
||||||
task copyCasConfiguration(type: Copy, group: "build", description: "Copy the CAS configuration from this project to /etc/cas/config") {
|
task copyCasConfiguration(type: Copy, group: "build", description: "Copy the CAS configuration from this project to /etc/cas/config") {
|
||||||
from "etc/cas/config"
|
from "etc/cas/config"
|
||||||
|
|
@ -47,12 +49,22 @@ task explodeWarOnly(type: Copy, group: "build", description: "Explodes the CAS w
|
||||||
dependsOn 'build'
|
dependsOn 'build'
|
||||||
from zipTree("build/libs/${casWebApplicationBinaryName}")
|
from zipTree("build/libs/${casWebApplicationBinaryName}")
|
||||||
into explodedDir
|
into explodedDir
|
||||||
|
doLast {
|
||||||
|
println "Exploded WAR into ${explodedDir}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task explodeWar(type: Copy, group: "build", description: "Explodes the CAS archive and resources jar from the CAS web application archive") {
|
task explodeWar(type: Copy, group: "build", description: "Explodes the CAS archive and resources jar from the CAS web application archive") {
|
||||||
dependsOn explodeWarOnly
|
dependsOn explodeWarOnly
|
||||||
from zipTree("${explodedDir}/WEB-INF/lib/${resourceJarName}-${casServerVersion}.jar")
|
from zipTree("${explodedDir}/WEB-INF/lib/${templateViewsJarName}-${casServerVersion}.jar")
|
||||||
into explodedResourcesDir
|
into explodedResourcesDir
|
||||||
|
|
||||||
|
from zipTree("${explodedDir}/WEB-INF/lib/${resourcesJarName}-${casServerVersion}.jar")
|
||||||
|
into explodedResourcesDir
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
println "Exploded WAR resources into ${explodedResourcesDir}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task run(group: "build", description: "Run the CAS web application in embedded container mode") {
|
task run(group: "build", description: "Run the CAS web application in embedded container mode") {
|
||||||
|
|
@ -222,9 +234,11 @@ task listTemplateViews(group: "build", description: "List all CAS views") {
|
||||||
fileTree(explodedResourcesDir).matching {
|
fileTree(explodedResourcesDir).matching {
|
||||||
include "**/*.html"
|
include "**/*.html"
|
||||||
}
|
}
|
||||||
.collect { it.name }
|
.collect {
|
||||||
.toSorted()
|
return it.path.replace(explodedResourcesDir, "")
|
||||||
.each { println it }
|
}
|
||||||
|
.toSorted()
|
||||||
|
.each { println it }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -300,7 +314,11 @@ task getResource(group: "build", description: "Fetch a CAS resource and move it
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (results.size() > 1) {
|
if (results.size() > 1) {
|
||||||
println "Multiple resources found matching ${resourceName}: ${results}"
|
println "Multiple resources found matching ${resourceName}:\n"
|
||||||
|
results.each {
|
||||||
|
println "\t-" + it.path.replace(explodedResourcesDir, "")
|
||||||
|
}
|
||||||
|
println "\nNarrow down your search criteria and try again."
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,282 @@
|
||||||
|
package org.apereo.cas.support.oauth.web.response.accesstoken;
|
||||||
|
|
||||||
|
import org.apereo.cas.authentication.DefaultAuthenticationBuilder;
|
||||||
|
import org.apereo.cas.configuration.CasConfigurationProperties;
|
||||||
|
import org.apereo.cas.configuration.support.Beans;
|
||||||
|
import org.apereo.cas.support.oauth.OAuth20Constants;
|
||||||
|
import org.apereo.cas.support.oauth.OAuth20ResponseTypes;
|
||||||
|
import org.apereo.cas.support.oauth.validator.token.device.InvalidOAuth20DeviceTokenException;
|
||||||
|
import org.apereo.cas.support.oauth.validator.token.device.ThrottledOAuth20DeviceUserCodeApprovalException;
|
||||||
|
import org.apereo.cas.support.oauth.validator.token.device.UnapprovedOAuth20DeviceUserCodeException;
|
||||||
|
import org.apereo.cas.support.oauth.web.response.accesstoken.ext.AccessTokenRequestDataHolder;
|
||||||
|
import org.apereo.cas.ticket.Ticket;
|
||||||
|
import org.apereo.cas.ticket.TicketGrantingTicket;
|
||||||
|
import org.apereo.cas.ticket.TicketState;
|
||||||
|
import org.apereo.cas.ticket.accesstoken.OAuth20AccessToken;
|
||||||
|
import org.apereo.cas.ticket.accesstoken.OAuth20AccessTokenFactory;
|
||||||
|
import org.apereo.cas.ticket.code.OAuth20Code;
|
||||||
|
import org.apereo.cas.ticket.device.OAuth20DeviceToken;
|
||||||
|
import org.apereo.cas.ticket.device.OAuth20DeviceTokenFactory;
|
||||||
|
import org.apereo.cas.ticket.device.OAuth20DeviceUserCode;
|
||||||
|
import org.apereo.cas.ticket.refreshtoken.OAuth20RefreshToken;
|
||||||
|
import org.apereo.cas.ticket.refreshtoken.OAuth20RefreshTokenFactory;
|
||||||
|
import org.apereo.cas.ticket.registry.TicketRegistry;
|
||||||
|
import org.apereo.cas.util.function.FunctionUtils;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import lombok.val;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.ZonedDateTime;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is {@link OAuth20DefaultTokenGenerator}.
|
||||||
|
*
|
||||||
|
* @author Misagh Moayyed
|
||||||
|
* @since 5.2.0
|
||||||
|
*/
|
||||||
|
@Transactional(transactionManager = "ticketTransactionManager")
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class OAuth20DefaultTokenGenerator implements OAuth20TokenGenerator {
|
||||||
|
/**
|
||||||
|
* The Access token factory.
|
||||||
|
*/
|
||||||
|
protected final OAuth20AccessTokenFactory accessTokenFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The device token factory.
|
||||||
|
*/
|
||||||
|
protected final OAuth20DeviceTokenFactory deviceTokenFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The refresh token factory.
|
||||||
|
*/
|
||||||
|
protected final OAuth20RefreshTokenFactory refreshTokenFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Ticket registry.
|
||||||
|
*/
|
||||||
|
protected final TicketRegistry ticketRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CAS configuration settings.
|
||||||
|
*/
|
||||||
|
protected final CasConfigurationProperties casProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuth20TokenGeneratedResult generate(final AccessTokenRequestDataHolder holder) {
|
||||||
|
if (OAuth20ResponseTypes.DEVICE_CODE.equals(holder.getResponseType())) {
|
||||||
|
return generateAccessTokenOAuthDeviceCodeResponseType(holder);
|
||||||
|
}
|
||||||
|
|
||||||
|
val pair = generateAccessTokenOAuthGrantTypes(holder);
|
||||||
|
return generateAccessTokenResult(holder, pair);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate access token OAuth device code response type OAuth token generated result.
|
||||||
|
*
|
||||||
|
* @param holder the holder
|
||||||
|
* @return the OAuth token generated result
|
||||||
|
*/
|
||||||
|
protected OAuth20TokenGeneratedResult generateAccessTokenOAuthDeviceCodeResponseType(final AccessTokenRequestDataHolder holder) {
|
||||||
|
val deviceCode = holder.getDeviceCode();
|
||||||
|
|
||||||
|
if (StringUtils.isNotBlank(deviceCode)) {
|
||||||
|
val deviceCodeTicket = getDeviceTokenFromTicketRegistry(deviceCode);
|
||||||
|
val deviceUserCode = getDeviceUserCodeFromRegistry(deviceCodeTicket);
|
||||||
|
|
||||||
|
if (deviceUserCode.isUserCodeApproved()) {
|
||||||
|
this.ticketRegistry.deleteTicket(deviceCode);
|
||||||
|
|
||||||
|
val deviceResult = AccessTokenRequestDataHolder.builder()
|
||||||
|
.service(holder.getService())
|
||||||
|
.authentication(holder.getAuthentication())
|
||||||
|
.registeredService(holder.getRegisteredService())
|
||||||
|
.ticketGrantingTicket(holder.getTicketGrantingTicket())
|
||||||
|
.grantType(holder.getGrantType())
|
||||||
|
.scopes(new LinkedHashSet<>(0))
|
||||||
|
.responseType(holder.getResponseType())
|
||||||
|
.generateRefreshToken(holder.getRegisteredService() != null && holder.isGenerateRefreshToken())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
val ticketPair = generateAccessTokenOAuthGrantTypes(deviceResult);
|
||||||
|
return generateAccessTokenResult(deviceResult, ticketPair);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deviceCodeTicket.getLastTimeUsed() != null) {
|
||||||
|
val interval = Beans.newDuration(casProperties.getAuthn().getOauth().getDeviceToken().getRefreshInterval()).getSeconds();
|
||||||
|
val shouldSlowDown = deviceCodeTicket.getLastTimeUsed().plusSeconds(interval).isAfter(ZonedDateTime.now(ZoneOffset.UTC));
|
||||||
|
if (shouldSlowDown) {
|
||||||
|
throw new ThrottledOAuth20DeviceUserCodeApprovalException(deviceCodeTicket.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deviceCodeTicket.update();
|
||||||
|
this.ticketRegistry.updateTicket(deviceCodeTicket);
|
||||||
|
throw new UnapprovedOAuth20DeviceUserCodeException(deviceCodeTicket.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
val deviceTokens = createDeviceTokensInTicketRegistry(holder);
|
||||||
|
return OAuth20TokenGeneratedResult.builder()
|
||||||
|
.responseType(holder.getResponseType())
|
||||||
|
.registeredService(holder.getRegisteredService())
|
||||||
|
.deviceCode(deviceTokens.getLeft().getId())
|
||||||
|
.userCode(deviceTokens.getValue().getId())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuth20DeviceUserCode getDeviceUserCodeFromRegistry(final OAuth20DeviceToken deviceCodeTicket) {
|
||||||
|
val userCode = this.ticketRegistry.getTicket(deviceCodeTicket.getUserCode(), OAuth20DeviceUserCode.class);
|
||||||
|
if (userCode == null) {
|
||||||
|
throw new InvalidOAuth20DeviceTokenException(deviceCodeTicket.getUserCode());
|
||||||
|
}
|
||||||
|
if (userCode.isExpired()) {
|
||||||
|
this.ticketRegistry.deleteTicket(userCode.getId());
|
||||||
|
throw new InvalidOAuth20DeviceTokenException(deviceCodeTicket.getUserCode());
|
||||||
|
}
|
||||||
|
return userCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private OAuth20DeviceToken getDeviceTokenFromTicketRegistry(final String deviceCode) {
|
||||||
|
val deviceCodeTicket = this.ticketRegistry.getTicket(deviceCode, OAuth20DeviceToken.class);
|
||||||
|
if (deviceCodeTicket == null) {
|
||||||
|
throw new InvalidOAuth20DeviceTokenException(deviceCode);
|
||||||
|
}
|
||||||
|
if (deviceCodeTicket.isExpired()) {
|
||||||
|
this.ticketRegistry.deleteTicket(deviceCode);
|
||||||
|
throw new InvalidOAuth20DeviceTokenException(deviceCode);
|
||||||
|
}
|
||||||
|
return deviceCodeTicket;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Pair<OAuth20DeviceToken, OAuth20DeviceUserCode> createDeviceTokensInTicketRegistry(final AccessTokenRequestDataHolder holder) {
|
||||||
|
val deviceToken = deviceTokenFactory.createDeviceCode(holder.getService());
|
||||||
|
|
||||||
|
val deviceUserCode = deviceTokenFactory.createDeviceUserCode(deviceToken);
|
||||||
|
|
||||||
|
addTicketToRegistry(deviceToken);
|
||||||
|
|
||||||
|
addTicketToRegistry(deviceUserCode);
|
||||||
|
|
||||||
|
return Pair.of(deviceToken, deviceUserCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate access token OAuth grant types pair.
|
||||||
|
*
|
||||||
|
* @param holder the holder
|
||||||
|
* @return the pair
|
||||||
|
*/
|
||||||
|
protected Pair<OAuth20AccessToken, OAuth20RefreshToken> generateAccessTokenOAuthGrantTypes(final AccessTokenRequestDataHolder holder) {
|
||||||
|
val clientId = holder.getRegisteredService().getClientId();
|
||||||
|
val authn = DefaultAuthenticationBuilder
|
||||||
|
.newInstance(holder.getAuthentication())
|
||||||
|
.setAuthenticationDate(ZonedDateTime.now(ZoneOffset.UTC))
|
||||||
|
.addAttribute(OAuth20Constants.GRANT_TYPE, holder.getGrantType().toString())
|
||||||
|
.addAttribute(OAuth20Constants.SCOPE, holder.getScopes())
|
||||||
|
.addAttribute(OAuth20Constants.CLIENT_ID, clientId)
|
||||||
|
.addAttribute(OAuth20Constants.CLAIMS, holder.getClaims())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
val ticketGrantingTicket = holder.getTicketGrantingTicket();
|
||||||
|
val accessToken = this.accessTokenFactory.create(holder.getService(),
|
||||||
|
authn, ticketGrantingTicket, holder.getScopes(),
|
||||||
|
clientId, holder.getClaims());
|
||||||
|
|
||||||
|
addTicketToRegistry(accessToken, ticketGrantingTicket);
|
||||||
|
|
||||||
|
updateOAuthCode(holder);
|
||||||
|
|
||||||
|
val refreshToken = FunctionUtils.doIf(holder.isGenerateRefreshToken(),
|
||||||
|
() -> generateRefreshToken(holder),
|
||||||
|
() -> {
|
||||||
|
return null;
|
||||||
|
}).get();
|
||||||
|
|
||||||
|
return Pair.of(accessToken, refreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update OAuth code.
|
||||||
|
*
|
||||||
|
* @param holder the holder
|
||||||
|
*/
|
||||||
|
protected void updateOAuthCode(final AccessTokenRequestDataHolder holder) {
|
||||||
|
if (holder.getToken() instanceof OAuth20Code) {
|
||||||
|
val codeState = TicketState.class.cast(holder.getToken());
|
||||||
|
codeState.update();
|
||||||
|
|
||||||
|
if (holder.getToken().isExpired()) {
|
||||||
|
this.ticketRegistry.deleteTicket(holder.getToken().getId());
|
||||||
|
} else {
|
||||||
|
this.ticketRegistry.updateTicket(holder.getToken());
|
||||||
|
}
|
||||||
|
this.ticketRegistry.updateTicket(holder.getTicketGrantingTicket());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ticket to registry.
|
||||||
|
*
|
||||||
|
* @param ticket the ticket
|
||||||
|
* @param ticketGrantingTicket the ticket granting ticket
|
||||||
|
*/
|
||||||
|
protected void addTicketToRegistry(final Ticket ticket, final TicketGrantingTicket ticketGrantingTicket) {
|
||||||
|
this.ticketRegistry.addTicket(ticket);
|
||||||
|
if (ticketGrantingTicket != null) {
|
||||||
|
this.ticketRegistry.updateTicket(ticketGrantingTicket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add ticket to registry.
|
||||||
|
*
|
||||||
|
* @param ticket the ticket
|
||||||
|
*/
|
||||||
|
protected void addTicketToRegistry(final Ticket ticket) {
|
||||||
|
addTicketToRegistry(ticket, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate refresh token.
|
||||||
|
*
|
||||||
|
* @param responseHolder the response holder
|
||||||
|
* @return the refresh token
|
||||||
|
*/
|
||||||
|
protected OAuth20RefreshToken generateRefreshToken(final AccessTokenRequestDataHolder responseHolder) {
|
||||||
|
val refreshToken = this.refreshTokenFactory.create(responseHolder.getService(),
|
||||||
|
responseHolder.getAuthentication(),
|
||||||
|
responseHolder.getTicketGrantingTicket(),
|
||||||
|
responseHolder.getScopes(),
|
||||||
|
responseHolder.getClientId(),
|
||||||
|
responseHolder.getClaims());
|
||||||
|
addTicketToRegistry(refreshToken, responseHolder.getTicketGrantingTicket());
|
||||||
|
if (responseHolder.isExpireOldRefreshToken()) {
|
||||||
|
expireOldRefreshToken(responseHolder);
|
||||||
|
}
|
||||||
|
return refreshToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expireOldRefreshToken(final AccessTokenRequestDataHolder responseHolder) {
|
||||||
|
val oldRefreshToken = responseHolder.getToken();
|
||||||
|
oldRefreshToken.markTicketExpired();
|
||||||
|
ticketRegistry.deleteTicket(oldRefreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static OAuth20TokenGeneratedResult generateAccessTokenResult(final AccessTokenRequestDataHolder holder,
|
||||||
|
final Pair<OAuth20AccessToken, OAuth20RefreshToken> pair) {
|
||||||
|
return OAuth20TokenGeneratedResult.builder()
|
||||||
|
.registeredService(holder.getRegisteredService())
|
||||||
|
.accessToken(pair.getKey())
|
||||||
|
.refreshToken(pair.getValue())
|
||||||
|
.grantType(holder.getGrantType())
|
||||||
|
.responseType(holder.getResponseType())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue