001/*******************************************************************************
002 * Copyright 2017 The MIT Internet Trust Consortium
003 *
004 * Portions copyright 2011-2013 The MITRE Corporation
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 *******************************************************************************/
018/**
019 *
020 */
021package org.mitre.openid.connect.web;
022
023import java.lang.reflect.Type;
024
025import javax.servlet.http.HttpServletRequest;
026import javax.servlet.http.HttpServletResponse;
027
028import org.mitre.openid.connect.model.OIDCAuthenticationToken;
029import org.mitre.openid.connect.model.UserInfo;
030import org.mitre.openid.connect.service.UserInfoService;
031import org.springframework.beans.factory.annotation.Autowired;
032import org.springframework.security.authentication.AuthenticationTrustResolver;
033import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
034import org.springframework.security.core.Authentication;
035import org.springframework.security.core.GrantedAuthority;
036import org.springframework.security.core.context.SecurityContextHolder;
037import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
038
039import com.google.gson.Gson;
040import com.google.gson.GsonBuilder;
041import com.google.gson.JsonElement;
042import com.google.gson.JsonPrimitive;
043import com.google.gson.JsonSerializationContext;
044import com.google.gson.JsonSerializer;
045
046/**
047 * Injects the UserInfo object for the current user into the current model's context, if both exist. Allows JSPs and the like to call "userInfo.name" and other fields.
048 *
049 * @author jricher
050 *
051 */
052public class UserInfoInterceptor extends HandlerInterceptorAdapter {
053
054        private Gson gson = new GsonBuilder()
055                        .registerTypeHierarchyAdapter(GrantedAuthority.class, new JsonSerializer<GrantedAuthority>() {
056                                @Override
057                                public JsonElement serialize(GrantedAuthority src, Type typeOfSrc, JsonSerializationContext context) {
058                                        return new JsonPrimitive(src.getAuthority());
059                                }
060                        })
061                        .create();
062
063        @Autowired (required = false)
064        private UserInfoService userInfoService;
065
066        private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
067
068        @Override
069        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
070
071                Authentication auth = SecurityContextHolder.getContext().getAuthentication();
072
073                if (auth instanceof Authentication){
074                        request.setAttribute("userAuthorities", gson.toJson(auth.getAuthorities()));
075                }
076
077                if (!trustResolver.isAnonymous(auth)) { // skip lookup on anonymous logins
078                        if (auth instanceof OIDCAuthenticationToken) {
079                                // if they're logging into this server from a remote OIDC server, pass through their user info
080                                OIDCAuthenticationToken oidc = (OIDCAuthenticationToken) auth;
081                                if (oidc.getUserInfo() != null) {
082                                        request.setAttribute("userInfo", oidc.getUserInfo());
083                                        request.setAttribute("userInfoJson", oidc.getUserInfo().toJson());
084                                } else {
085                                        request.setAttribute("userInfo", null);
086                                        request.setAttribute("userInfoJson", "null");
087                                }
088                        } else {
089                                // don't bother checking if we don't have a principal or a userInfoService to work with
090                                if (auth != null && auth.getName() != null && userInfoService != null) {
091
092                                        // try to look up a user based on the principal's name
093                                        UserInfo user = userInfoService.getByUsername(auth.getName());
094
095                                        // if we have one, inject it so views can use it
096                                        if (user != null) {
097                                                request.setAttribute("userInfo", user);
098                                                request.setAttribute("userInfoJson", user.toJson());
099                                        }
100                                }
101                        }
102                }
103
104                return true;
105        }
106
107}