001/*
002 * (C) Copyright 2006-2013 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nelson Silva <nelson.silva@inevo.pt>
016 */
017package org.nuxeo.ecm.platform.oauth2.openid.auth;
018
019import java.io.Serializable;
020import java.util.HashMap;
021import java.util.Map;
022
023import org.apache.commons.logging.Log;
024import org.apache.commons.logging.LogFactory;
025import org.nuxeo.ecm.core.api.DocumentModel;
026import org.nuxeo.ecm.core.api.DocumentModelList;
027import org.nuxeo.ecm.core.api.model.PropertyNotFoundException;
028import org.nuxeo.ecm.directory.DirectoryException;
029import org.nuxeo.ecm.directory.Session;
030import org.nuxeo.ecm.directory.api.DirectoryService;
031import org.nuxeo.runtime.api.Framework;
032
033public class OpenIDUserInfoStoreImpl implements OpenIDUserInfoStore {
034
035    protected static final Log log = LogFactory.getLog(OpenIDUserInfoStoreImpl.class);
036
037    public static final String DIRECTORY_NAME = "openIdUserInfos";
038
039    public static final String SCHEMA_NAME = "openIdUserInfo";
040
041    public static final String NUXEO_LOGIN_KEY = "nuxeoLogin";
042
043    public static final String OPENID_SUBJECT_KEY = "subject";
044
045    public static final String OPENID_PROVIDER_KEY = "provider";
046
047    public static final String ID = "id";
048
049    private String providerName;
050
051    public OpenIDUserInfoStoreImpl(String providerName) {
052        this.providerName = providerName;
053    }
054
055    @Override
056    public void storeUserInfo(String userId, OpenIDUserInfo userInfo) {
057        DirectoryService ds = Framework.getService(DirectoryService.class);
058        try (Session session = ds.open(DIRECTORY_NAME)) {
059            Map<String, Object> data = new HashMap<String, Object>();
060
061            // Generate an ID
062            String userInfoId = getID(providerName, userInfo.getSubject());
063
064            data.put(NUXEO_LOGIN_KEY, userId);
065            data.put(OPENID_PROVIDER_KEY, providerName);
066
067            // Copy the standard fields
068            data.put(OPENID_SUBJECT_KEY, userInfo.getSubject());
069            data.put("name", userInfo.getName());
070            data.put("given_name", userInfo.getGivenName());
071            data.put("family_name", userInfo.getFamilyName());
072            data.put("middle_name", userInfo.getMiddleName());
073            data.put("nickname", userInfo.getNickname());
074            data.put("preferred_username", userInfo.getPreferredUsername());
075            data.put("profile", userInfo.getProfile());
076            data.put("picture", userInfo.getPicture());
077            data.put("website", userInfo.getWebsite());
078            data.put("email", userInfo.getEmail());
079            data.put("email_verified", userInfo.isEmailVerified());
080            data.put("gender", userInfo.getGender());
081            data.put("birthdate", userInfo.getBirthdate());
082            data.put("zoneinfo", userInfo.getZoneInfo());
083            data.put("locale", userInfo.getLocale());
084            data.put("phone_number", userInfo.getPhoneNumber());
085            data.put("address", userInfo.getAddress());
086            data.put("updated_time", userInfo.getUpdatedTime());
087
088            if (session.hasEntry(userInfoId)) {
089                DocumentModel userInfoDoc = session.getEntry(userInfoId);
090                userInfoDoc.setProperties(SCHEMA_NAME, data);
091                session.updateEntry(userInfoDoc);
092            } else {
093                data.put(ID, userInfoId);
094                session.createEntry(data);
095            }
096
097        } catch (DirectoryException e) {
098            log.error("Error during token storage", e);
099        }
100    }
101
102    @Override
103    public String getNuxeoLogin(OpenIDUserInfo userInfo) {
104        DirectoryService ds = Framework.getService(DirectoryService.class);
105        try (Session session = ds.open(DIRECTORY_NAME)) {
106            DocumentModel entry = session.getEntry(getID(providerName, userInfo.getSubject()));
107            if (entry == null) {
108                return null;
109            }
110            return (String) entry.getPropertyValue(SCHEMA_NAME + ":" + NUXEO_LOGIN_KEY);
111        } catch (PropertyNotFoundException e) {
112            log.error("Error retrieving OpenID user info", e);
113            return null;
114        }
115    }
116
117    @Override
118    public OpenIDUserInfo getUserInfo(String nuxeoLogin) {
119        DirectoryService ds = Framework.getService(DirectoryService.class);
120        try (Session session = ds.open(DIRECTORY_NAME)) {
121            Map<String, Serializable> filter = new HashMap<String, Serializable>();
122            filter.put(OPENID_PROVIDER_KEY, providerName);
123            filter.put(NUXEO_LOGIN_KEY, nuxeoLogin);
124            DocumentModelList entries = session.query(filter);
125            if (entries.size() == 0) {
126                return null;
127            }
128            DocumentModel entry = entries.get(0);
129            DefaultOpenIDUserInfo userInfo = new DefaultOpenIDUserInfo();
130            userInfo.putAll(entry.getProperties(SCHEMA_NAME));
131            return userInfo;
132        } catch (DirectoryException e) {
133            log.error("Error retrieving OpenID user info", e);
134            return null;
135        }
136    }
137
138    protected String getID(String provider, String subject) {
139        return subject + "@" + provider;
140    }
141
142}