Introduce introspection result assembler to allow for customized introspection results
parent
bf00c1f5e0
commit
9dfac35912
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2014 The MITRE Corporation
|
||||
* and the MIT Kerberos and Internet Trust Consortium
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.mitre.oauth2.service;
|
||||
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Strategy interface for assembling a token introspection result.
|
||||
*/
|
||||
public interface IntrospectionResultAssembler {
|
||||
|
||||
/**
|
||||
* Assemble a token introspection result from the given access token and user info.
|
||||
*
|
||||
* @param accessToken the access token
|
||||
* @param userInfo the user info
|
||||
* @return the token introspection result
|
||||
*/
|
||||
Map<String, Object> assembleFrom(OAuth2AccessTokenEntity accessToken, UserInfo userInfo);
|
||||
|
||||
/**
|
||||
* Assemble a token introspection result from the given refresh token and user info.
|
||||
*
|
||||
* @param refreshToken the refresh token
|
||||
* @param userInfo the user info
|
||||
* @return the token introspection result
|
||||
*/
|
||||
Map<String, Object> assembleFrom(OAuth2RefreshTokenEntity refreshToken, UserInfo userInfo);
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2014 The MITRE Corporation
|
||||
* and the MIT Kerberos and Internet Trust Consortium
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.mitre.oauth2.service.impl;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
|
||||
import org.mitre.oauth2.service.IntrospectionResultAssembler;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static com.google.common.collect.Maps.newLinkedHashMap;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link IntrospectionResultAssembler} interface.
|
||||
*/
|
||||
@Service
|
||||
public class DefaultIntrospectionResultAssembler implements IntrospectionResultAssembler {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> assembleFrom(OAuth2AccessTokenEntity accessToken, UserInfo userInfo) {
|
||||
|
||||
Map<String, Object> result = newLinkedHashMap();
|
||||
OAuth2Authentication authentication = accessToken.getAuthenticationHolder().getAuthentication();
|
||||
|
||||
result.put("active", true);
|
||||
|
||||
result.put("scope", Joiner.on(" ").join(accessToken.getScope()));
|
||||
|
||||
if (accessToken.getExpiration() != null) {
|
||||
result.put("exp", accessToken.getExpiration());
|
||||
}
|
||||
|
||||
if (userInfo != null) {
|
||||
// if we have a UserInfo, use that for the subject
|
||||
result.put("sub", userInfo.getSub());
|
||||
} else {
|
||||
// otherwise, use the authentication's username
|
||||
result.put("sub", authentication.getName());
|
||||
}
|
||||
|
||||
result.put("user_id", authentication.getName());
|
||||
|
||||
result.put("client_id", authentication.getOAuth2Request().getClientId());
|
||||
|
||||
result.put("token_type", accessToken.getTokenType());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> assembleFrom(OAuth2RefreshTokenEntity refreshToken, UserInfo userInfo) {
|
||||
|
||||
Map<String, Object> result = newLinkedHashMap();
|
||||
OAuth2Authentication authentication = refreshToken.getAuthenticationHolder().getAuthentication();
|
||||
|
||||
result.put("active", true);
|
||||
|
||||
result.put("scope", Joiner.on(" ").join(authentication.getOAuth2Request().getScope()));
|
||||
|
||||
if (refreshToken.getExpiration() != null) {
|
||||
result.put("exp", refreshToken.getExpiration());
|
||||
}
|
||||
|
||||
if (userInfo != null) {
|
||||
// if we have a UserInfo, use that for the subject
|
||||
result.put("sub", userInfo.getSub());
|
||||
} else {
|
||||
// otherwise, use the authentication's username
|
||||
result.put("sub", authentication.getName());
|
||||
}
|
||||
|
||||
result.put("user_id", authentication.getName());
|
||||
|
||||
result.put("client_id", authentication.getOAuth2Request().getClientId());
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2014 The MITRE Corporation
|
||||
* and the MIT Kerberos and Internet Trust Consortium
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.mitre.oauth2.view;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.swing.text.DateFormatter;
|
||||
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.view.AbstractView;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
@Component(TokenIntrospectionView.VIEWNAME)
|
||||
public class TokenIntrospectionView extends AbstractView {
|
||||
|
||||
public static final String VIEWNAME = "tokenIntrospection";
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(TokenIntrospectionView.class);
|
||||
|
||||
private static DateFormatter isoDateFormatter = new DateFormatter(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"));
|
||||
|
||||
private Gson gson = new GsonBuilder().create();
|
||||
|
||||
@Override
|
||||
protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
response.setContentType("application/json");
|
||||
|
||||
Writer out;
|
||||
|
||||
try {
|
||||
|
||||
out = response.getWriter();
|
||||
UserInfo user = (UserInfo)model.get("user");
|
||||
Object obj = model.get("token");
|
||||
if (obj instanceof OAuth2AccessTokenEntity) {
|
||||
gson.toJson(renderAccessToken((OAuth2AccessTokenEntity)obj, user), out);
|
||||
} else if (obj instanceof OAuth2RefreshTokenEntity) {
|
||||
gson.toJson(renderRefreshToken((OAuth2RefreshTokenEntity)obj, user), out);
|
||||
} else {
|
||||
throw new IOException("Couldn't find a valid entity to render");
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
|
||||
logger.error("IOException occurred in TokenIntrospectionView.java: ", e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private JsonObject renderAccessToken(OAuth2AccessTokenEntity src, UserInfo user) {
|
||||
JsonObject token = new JsonObject();
|
||||
|
||||
token.addProperty("active", true);
|
||||
|
||||
token.addProperty("scope", Joiner.on(" ").join(src.getScope()));
|
||||
|
||||
if (src.getExpiration() != null) {
|
||||
try {
|
||||
token.addProperty("exp", isoDateFormatter.valueToString(src.getExpiration()));
|
||||
} catch (ParseException e) {
|
||||
logger.error("Problem formatting expiration date: " + src.getExpiration(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (user != null) {
|
||||
// if we have a UserInfo, use that for the subject
|
||||
token.addProperty("sub", user.getSub());
|
||||
token.addProperty("user_id", src.getAuthenticationHolder().getAuthentication().getName());
|
||||
} else {
|
||||
// otherwise, use the authentication's username
|
||||
token.addProperty("sub", src.getAuthenticationHolder().getAuthentication().getName());
|
||||
token.addProperty("user_id", src.getAuthenticationHolder().getAuthentication().getName());
|
||||
}
|
||||
|
||||
token.addProperty("client_id", src.getAuthenticationHolder().getAuthentication().getOAuth2Request().getClientId());
|
||||
|
||||
token.addProperty("token_type", src.getTokenType());
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
private JsonObject renderRefreshToken(OAuth2RefreshTokenEntity src, UserInfo user) {
|
||||
JsonObject token = new JsonObject();
|
||||
|
||||
token.addProperty("active", true);
|
||||
|
||||
token.addProperty("scope", Joiner.on(" ").join(src.getAuthenticationHolder().getAuthentication().getOAuth2Request().getScope()));
|
||||
|
||||
if (src.getExpiration() != null) {
|
||||
try {
|
||||
token.addProperty("exp", isoDateFormatter.valueToString(src.getExpiration()));
|
||||
} catch (ParseException e) {
|
||||
logger.error("Problem formatting expiration date: " + src.getExpiration(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (user != null) {
|
||||
// if we have a UserInfo, use that for the subject
|
||||
token.addProperty("sub", user.getSub());
|
||||
token.addProperty("user_id", src.getAuthenticationHolder().getAuthentication().getName());
|
||||
} else {
|
||||
// otherwise, use the authentication's username
|
||||
token.addProperty("sub", src.getAuthenticationHolder().getAuthentication().getName());
|
||||
token.addProperty("user_id", src.getAuthenticationHolder().getAuthentication().getName());
|
||||
}
|
||||
|
||||
token.addProperty("client_id", src.getAuthenticationHolder().getAuthentication().getOAuth2Request().getClientId());
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2014 The MITRE Corporation
|
||||
* and the MIT Kerberos and Internet Trust Consortium
|
||||
*
|
||||
*
|
||||
* 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
|
||||
*
|
||||
*
|
||||
* http://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.
|
||||
|
@ -16,17 +16,15 @@
|
|||
******************************************************************************/
|
||||
package org.mitre.oauth2.web;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
|
||||
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||
import org.mitre.oauth2.service.IntrospectionAuthorizer;
|
||||
import org.mitre.oauth2.service.IntrospectionResultAssembler;
|
||||
import org.mitre.oauth2.service.OAuth2TokenEntityService;
|
||||
import org.mitre.oauth2.view.TokenIntrospectionView;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.mitre.openid.connect.service.UserInfoService;
|
||||
import org.mitre.openid.connect.view.HttpCodeView;
|
||||
|
@ -42,8 +40,9 @@ import org.springframework.ui.Model;
|
|||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@Controller
|
||||
public class IntrospectionEndpoint {
|
||||
|
@ -56,7 +55,10 @@ public class IntrospectionEndpoint {
|
|||
|
||||
@Autowired
|
||||
private IntrospectionAuthorizer introspectionAuthorizer;
|
||||
|
||||
|
||||
@Autowired
|
||||
private IntrospectionResultAssembler introspectionResultAssembler;
|
||||
|
||||
@Autowired
|
||||
private UserInfoService userInfoService;
|
||||
|
||||
|
@ -84,72 +86,64 @@ public class IntrospectionEndpoint {
|
|||
return JsonEntityView.VIEWNAME;
|
||||
}
|
||||
|
||||
// clientID is the principal name in the authentication
|
||||
String clientId = p.getName();
|
||||
ClientDetailsEntity authClient = clientService.loadClientByClientId(clientId);
|
||||
|
||||
ClientDetailsEntity tokenClient = null;
|
||||
Set<String> scopes = null;
|
||||
Object token = null;
|
||||
UserInfo user = null;
|
||||
OAuth2AccessTokenEntity accessToken = null;
|
||||
OAuth2RefreshTokenEntity refreshToken = null;
|
||||
ClientDetailsEntity tokenClient;
|
||||
Set<String> scopes;
|
||||
UserInfo user;
|
||||
|
||||
try {
|
||||
|
||||
// check access tokens first (includes ID tokens)
|
||||
OAuth2AccessTokenEntity access = tokenServices.readAccessToken(tokenValue);
|
||||
accessToken = tokenServices.readAccessToken(tokenValue);
|
||||
|
||||
tokenClient = access.getClient();
|
||||
scopes = access.getScope();
|
||||
tokenClient = accessToken.getClient();
|
||||
scopes = accessToken.getScope();
|
||||
|
||||
token = access;
|
||||
user = userInfoService.getByUsernameAndClientId(accessToken.getAuthenticationHolder().getAuthentication().getName(), tokenClient.getClientId());
|
||||
|
||||
user = userInfoService.getByUsernameAndClientId(access.getAuthenticationHolder().getAuthentication().getName(), tokenClient.getClientId());
|
||||
|
||||
} catch (InvalidTokenException e) {
|
||||
logger.error("Verify failed; Invalid access token. Checking refresh token.", e);
|
||||
logger.info("Verify failed; Invalid access token. Checking refresh token.");
|
||||
try {
|
||||
|
||||
// check refresh tokens next
|
||||
OAuth2RefreshTokenEntity refresh = tokenServices.getRefreshToken(tokenValue);
|
||||
refreshToken = tokenServices.getRefreshToken(tokenValue);
|
||||
|
||||
tokenClient = refresh.getClient();
|
||||
scopes = refresh.getAuthenticationHolder().getAuthentication().getOAuth2Request().getScope();
|
||||
tokenClient = refreshToken.getClient();
|
||||
scopes = refreshToken.getAuthenticationHolder().getAuthentication().getOAuth2Request().getScope();
|
||||
|
||||
user = userInfoService.getByUsernameAndClientId(refresh.getAuthenticationHolder().getAuthentication().getName(), tokenClient.getClientId());
|
||||
|
||||
token = refresh;
|
||||
user = userInfoService.getByUsernameAndClientId(refreshToken.getAuthenticationHolder().getAuthentication().getName(), tokenClient.getClientId());
|
||||
|
||||
} catch (InvalidTokenException e2) {
|
||||
logger.error("Verify failed; Invalid refresh token", e2);
|
||||
logger.error("Verify failed; Invalid access/refresh token", e2);
|
||||
Map<String,Boolean> entity = ImmutableMap.of("active", Boolean.FALSE);
|
||||
model.addAttribute("entity", entity);
|
||||
return JsonEntityView.VIEWNAME;
|
||||
}
|
||||
}
|
||||
|
||||
if (tokenClient != null && authClient != null) {
|
||||
if (authClient.isAllowIntrospection()) {
|
||||
if (introspectionAuthorizer.isIntrospectionPermitted(authClient, tokenClient, scopes)) {
|
||||
// if it's a valid token, we'll print out information on it
|
||||
model.addAttribute("token", token);
|
||||
model.addAttribute("user", user);
|
||||
return TokenIntrospectionView.VIEWNAME;
|
||||
} else {
|
||||
logger.error("Verify failed; client configuration or scope don't permit token introspection");
|
||||
model.addAttribute("code", HttpStatus.FORBIDDEN);
|
||||
return HttpCodeView.VIEWNAME;
|
||||
}
|
||||
} else {
|
||||
logger.error("Verify failed; client " + clientId + " is not allowed to call introspection endpoint");
|
||||
model.addAttribute("code", HttpStatus.FORBIDDEN);
|
||||
return HttpCodeView.VIEWNAME;
|
||||
}
|
||||
} else {
|
||||
// This is a bad error -- I think it means we have a token outstanding that doesn't map to a client?
|
||||
logger.error("Verify failed; client " + clientId + " not found.");
|
||||
model.addAttribute("code", HttpStatus.NOT_FOUND);
|
||||
return HttpCodeView.VIEWNAME;
|
||||
}
|
||||
// clientID is the principal name in the authentication
|
||||
String clientId = p.getName();
|
||||
ClientDetailsEntity authClient = clientService.loadClientByClientId(clientId);
|
||||
|
||||
if (authClient.isAllowIntrospection()) {
|
||||
if (introspectionAuthorizer.isIntrospectionPermitted(authClient, tokenClient, scopes)) {
|
||||
// if it's a valid token, we'll print out information on it
|
||||
Map<String, Object> entity = accessToken != null
|
||||
? introspectionResultAssembler.assembleFrom(accessToken, user)
|
||||
: introspectionResultAssembler.assembleFrom(refreshToken, user);
|
||||
model.addAttribute("entity", entity);
|
||||
return JsonEntityView.VIEWNAME;
|
||||
} else {
|
||||
logger.error("Verify failed; client configuration or scope don't permit token introspection");
|
||||
model.addAttribute("code", HttpStatus.FORBIDDEN);
|
||||
return HttpCodeView.VIEWNAME;
|
||||
}
|
||||
} else {
|
||||
logger.error("Verify failed; client " + clientId + " is not allowed to call introspection endpoint");
|
||||
model.addAttribute("code", HttpStatus.FORBIDDEN);
|
||||
return HttpCodeView.VIEWNAME;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,230 @@
|
|||
/*******************************************************************************
|
||||
* Copyright 2014 The MITRE Corporation
|
||||
* and the MIT Kerberos and Internet Trust Consortium
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.mitre.oauth2.service.impl;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.junit.Test;
|
||||
import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
|
||||
import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
|
||||
import org.mitre.openid.connect.model.UserInfo;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Authentication;
|
||||
import org.springframework.security.oauth2.provider.OAuth2Request;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.collect.Sets.newHashSet;
|
||||
import static org.hamcrest.CoreMatchers.equalTo;
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class TestDefaultIntrospectionResultAssembler {
|
||||
|
||||
private DefaultIntrospectionResultAssembler assembler = new DefaultIntrospectionResultAssembler();
|
||||
|
||||
@Test
|
||||
public void shouldAssembleExpectedResultForAccessToken() {
|
||||
|
||||
// given
|
||||
OAuth2AccessTokenEntity accessToken = accessToken(new Date(123), scopes("foo", "bar"), "Bearer",
|
||||
authentication("name", request("clientId")));
|
||||
|
||||
UserInfo userInfo = userInfo("sub");
|
||||
|
||||
// when
|
||||
Map<String, Object> result = assembler.assembleFrom(accessToken, userInfo);
|
||||
|
||||
|
||||
// then
|
||||
Map<String, Object> expected = new ImmutableMap.Builder<String, Object>()
|
||||
.put("sub", "sub")
|
||||
.put("exp", new Date(123))
|
||||
.put("scope", "bar foo")
|
||||
.put("active", Boolean.TRUE)
|
||||
.put("user_id", "name")
|
||||
.put("client_id", "clientId")
|
||||
.put("token_type", "Bearer")
|
||||
.build();
|
||||
assertThat(result, is(equalTo(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAssembleExpectedResultForAccessTokenWithoutUserInfo() {
|
||||
|
||||
// given
|
||||
OAuth2AccessTokenEntity accessToken = accessToken(new Date(123), scopes("foo", "bar"), "Bearer",
|
||||
authentication("name", request("clientId")));
|
||||
|
||||
// when
|
||||
Map<String, Object> result = assembler.assembleFrom(accessToken, null);
|
||||
|
||||
|
||||
// then
|
||||
Map<String, Object> expected = new ImmutableMap.Builder<String, Object>()
|
||||
.put("sub", "name")
|
||||
.put("exp", new Date(123))
|
||||
.put("scope", "bar foo")
|
||||
.put("active", Boolean.TRUE)
|
||||
.put("user_id", "name")
|
||||
.put("client_id", "clientId")
|
||||
.put("token_type", "Bearer")
|
||||
.build();
|
||||
assertThat(result, is(equalTo(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAssembleExpectedResultForAccessTokenWithoutExpiry() {
|
||||
|
||||
// given
|
||||
OAuth2AccessTokenEntity accessToken = accessToken(null, scopes("foo", "bar"), "Bearer",
|
||||
authentication("name", request("clientId")));
|
||||
|
||||
UserInfo userInfo = userInfo("sub");
|
||||
|
||||
// when
|
||||
Map<String, Object> result = assembler.assembleFrom(accessToken, userInfo);
|
||||
|
||||
|
||||
// then
|
||||
Map<String, Object> expected = new ImmutableMap.Builder<String, Object>()
|
||||
.put("sub", "sub")
|
||||
.put("scope", "bar foo")
|
||||
.put("active", Boolean.TRUE)
|
||||
.put("user_id", "name")
|
||||
.put("client_id", "clientId")
|
||||
.put("token_type", "Bearer")
|
||||
.build();
|
||||
assertThat(result, is(equalTo(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAssembleExpectedResultForRefreshToken() {
|
||||
|
||||
// given
|
||||
OAuth2RefreshTokenEntity refreshToken = refreshToken(new Date(123),
|
||||
authentication("name", request("clientId", scopes("foo", "bar"))));
|
||||
|
||||
UserInfo userInfo = userInfo("sub");
|
||||
|
||||
// when
|
||||
Map<String, Object> result = assembler.assembleFrom(refreshToken, userInfo);
|
||||
|
||||
|
||||
// then
|
||||
Map<String, Object> expected = new ImmutableMap.Builder<String, Object>()
|
||||
.put("sub", "sub")
|
||||
.put("exp", new Date(123))
|
||||
.put("scope", "bar foo")
|
||||
.put("active", Boolean.TRUE)
|
||||
.put("user_id", "name")
|
||||
.put("client_id", "clientId")
|
||||
.build();
|
||||
assertThat(result, is(equalTo(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAssembleExpectedResultForRefreshTokenWithoutUserInfo() {
|
||||
|
||||
// given
|
||||
OAuth2RefreshTokenEntity refreshToken = refreshToken(new Date(123),
|
||||
authentication("name", request("clientId", scopes("foo", "bar"))));
|
||||
|
||||
// when
|
||||
Map<String, Object> result = assembler.assembleFrom(refreshToken, null);
|
||||
|
||||
|
||||
// then
|
||||
Map<String, Object> expected = new ImmutableMap.Builder<String, Object>()
|
||||
.put("sub", "name")
|
||||
.put("exp", new Date(123))
|
||||
.put("scope", "bar foo")
|
||||
.put("active", Boolean.TRUE)
|
||||
.put("user_id", "name")
|
||||
.put("client_id", "clientId")
|
||||
.build();
|
||||
assertThat(result, is(equalTo(expected)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldAssembleExpectedResultForRefreshTokenWithoutExpiry() {
|
||||
|
||||
// given
|
||||
OAuth2RefreshTokenEntity refreshToken = refreshToken(null,
|
||||
authentication("name", request("clientId", scopes("foo", "bar"))));
|
||||
|
||||
UserInfo userInfo = userInfo("sub");
|
||||
|
||||
// when
|
||||
Map<String, Object> result = assembler.assembleFrom(refreshToken, userInfo);
|
||||
|
||||
|
||||
// then
|
||||
Map<String, Object> expected = new ImmutableMap.Builder<String, Object>()
|
||||
.put("sub", "sub")
|
||||
.put("scope", "bar foo")
|
||||
.put("active", Boolean.TRUE)
|
||||
.put("user_id", "name")
|
||||
.put("client_id", "clientId")
|
||||
.build();
|
||||
assertThat(result, is(equalTo(expected)));
|
||||
}
|
||||
|
||||
private UserInfo userInfo(String sub) {
|
||||
UserInfo userInfo = mock(UserInfo.class);
|
||||
given(userInfo.getSub()).willReturn(sub);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
private OAuth2AccessTokenEntity accessToken(Date exp, Set<String> scopes, String tokenType, OAuth2Authentication authentication) {
|
||||
OAuth2AccessTokenEntity accessToken = mock(OAuth2AccessTokenEntity.class, RETURNS_DEEP_STUBS);
|
||||
given(accessToken.getExpiration()).willReturn(exp);
|
||||
given(accessToken.getScope()).willReturn(scopes);
|
||||
given(accessToken.getTokenType()).willReturn(tokenType);
|
||||
given(accessToken.getAuthenticationHolder().getAuthentication()).willReturn(authentication);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
private OAuth2RefreshTokenEntity refreshToken(Date exp, OAuth2Authentication authentication) {
|
||||
OAuth2RefreshTokenEntity refreshToken = mock(OAuth2RefreshTokenEntity.class, RETURNS_DEEP_STUBS);
|
||||
given(refreshToken.getExpiration()).willReturn(exp);
|
||||
given(refreshToken.getAuthenticationHolder().getAuthentication()).willReturn(authentication);
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
private OAuth2Authentication authentication(String name, OAuth2Request request) {
|
||||
OAuth2Authentication authentication = mock(OAuth2Authentication.class);
|
||||
given(authentication.getName()).willReturn(name);
|
||||
given(authentication.getOAuth2Request()).willReturn(request);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
private OAuth2Request request(String clientId) {
|
||||
return request(clientId, null);
|
||||
}
|
||||
|
||||
private OAuth2Request request(String clientId, Set<String> scopes) {
|
||||
return new OAuth2Request(null, clientId, null, true, scopes, null, null, null, null);
|
||||
}
|
||||
|
||||
private Set<String> scopes(String... scopes) {
|
||||
return newHashSet(scopes);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue