001/*******************************************************************************
002 * Copyright 2017 The MIT Internet Trust Consortium
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *   http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *******************************************************************************/
016package org.mitre.oauth2.service.impl;
017
018import static com.google.common.collect.Maps.newLinkedHashMap;
019
020import java.text.ParseException;
021import java.util.Map;
022import java.util.Set;
023
024import org.mitre.oauth2.model.OAuth2AccessTokenEntity;
025import org.mitre.oauth2.model.OAuth2RefreshTokenEntity;
026import org.mitre.oauth2.service.IntrospectionResultAssembler;
027import org.mitre.openid.connect.model.UserInfo;
028import org.mitre.uma.model.Permission;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031import org.springframework.security.oauth2.provider.OAuth2Authentication;
032import org.springframework.stereotype.Service;
033
034import com.google.common.base.Joiner;
035import com.google.common.collect.Sets;
036
037/**
038 * Default implementation of the {@link IntrospectionResultAssembler} interface.
039 */
040@Service
041public class DefaultIntrospectionResultAssembler implements IntrospectionResultAssembler {
042
043        /**
044         * Logger for this class
045         */
046        private static final Logger logger = LoggerFactory.getLogger(DefaultIntrospectionResultAssembler.class);
047
048        @Override
049        public Map<String, Object> assembleFrom(OAuth2AccessTokenEntity accessToken, UserInfo userInfo, Set<String> authScopes) {
050
051                Map<String, Object> result = newLinkedHashMap();
052                OAuth2Authentication authentication = accessToken.getAuthenticationHolder().getAuthentication();
053
054                result.put(ACTIVE, true);
055
056                if (accessToken.getPermissions() != null && !accessToken.getPermissions().isEmpty()) {
057
058                        Set<Object> permissions = Sets.newHashSet();
059
060                        for (Permission perm : accessToken.getPermissions()) {
061                                Map<String, Object> o = newLinkedHashMap();
062                                o.put("resource_set_id", perm.getResourceSet().getId().toString());
063                                Set<String> scopes = Sets.newHashSet(perm.getScopes());
064                                o.put("scopes", scopes);
065                                permissions.add(o);
066                        }
067
068                        result.put("permissions", permissions);
069
070                } else {
071                        Set<String> scopes = Sets.intersection(authScopes, accessToken.getScope());
072
073                        result.put(SCOPE, Joiner.on(SCOPE_SEPARATOR).join(scopes));
074
075                }
076
077                if (accessToken.getExpiration() != null) {
078                        try {
079                                result.put(EXPIRES_AT, dateFormat.valueToString(accessToken.getExpiration()));
080                                result.put(EXP, accessToken.getExpiration().getTime() / 1000L);
081                        } catch (ParseException e) {
082                                logger.error("Parse exception in token introspection", e);
083                        }
084                }
085
086                if (userInfo != null) {
087                        // if we have a UserInfo, use that for the subject
088                        result.put(SUB, userInfo.getSub());
089                } else {
090                        // otherwise, use the authentication's username
091                        result.put(SUB, authentication.getName());
092                }
093
094                if(authentication.getUserAuthentication() != null) {
095                        result.put(USER_ID, authentication.getUserAuthentication().getName());
096                }
097
098                result.put(CLIENT_ID, authentication.getOAuth2Request().getClientId());
099
100                result.put(TOKEN_TYPE, accessToken.getTokenType());
101
102                return result;
103        }
104
105        @Override
106        public Map<String, Object> assembleFrom(OAuth2RefreshTokenEntity refreshToken, UserInfo userInfo, Set<String> authScopes) {
107
108                Map<String, Object> result = newLinkedHashMap();
109                OAuth2Authentication authentication = refreshToken.getAuthenticationHolder().getAuthentication();
110
111                result.put(ACTIVE, true);
112
113                Set<String> scopes = Sets.intersection(authScopes, authentication.getOAuth2Request().getScope());
114
115                result.put(SCOPE, Joiner.on(SCOPE_SEPARATOR).join(scopes));
116
117                if (refreshToken.getExpiration() != null) {
118                        try {
119                                result.put(EXPIRES_AT, dateFormat.valueToString(refreshToken.getExpiration()));
120                                result.put(EXP, refreshToken.getExpiration().getTime() / 1000L);
121                        } catch (ParseException e) {
122                                logger.error("Parse exception in token introspection", e);
123                        }
124                }
125
126
127                if (userInfo != null) {
128                        // if we have a UserInfo, use that for the subject
129                        result.put(SUB, userInfo.getSub());
130                } else {
131                        // otherwise, use the authentication's username
132                        result.put(SUB, authentication.getName());
133                }
134
135                if(authentication.getUserAuthentication() != null) {
136                        result.put(USER_ID, authentication.getUserAuthentication().getName());
137                }
138
139                result.put(CLIENT_ID, authentication.getOAuth2Request().getClientId());
140
141                return result;
142        }
143}