diff options
author | Angel Avila | 2015-12-21 22:01:14 +0000 |
---|---|---|
committer | Ryan D. Brooks | 2015-12-21 22:01:14 +0000 |
commit | d7c359722bf1a6fd3ee5bd202657b273b3373409 (patch) | |
tree | 3f1e41663ba980d3b25c9f179ea72daf288988ec /plugins/org.eclipse.osee.jaxrs.server | |
parent | bf73e2f0b898bcf54aca7ee1fe76c3edeb0b8c76 (diff) | |
download | org.eclipse.osee-d7c359722bf1a6fd3ee5bd202657b273b3373409.tar.gz org.eclipse.osee-d7c359722bf1a6fd3ee5bd202657b273b3373409.tar.xz org.eclipse.osee-d7c359722bf1a6fd3ee5bd202657b273b3373409.zip |
bug: Enable OAuth to work with multiple servers through proxy
Change-Id: Ibb25c2ded9502745b9f91beb6e09fd53f2e10123
Conflicts:
plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/OAuthEncryption.java
Diffstat (limited to 'plugins/org.eclipse.osee.jaxrs.server')
19 files changed, 973 insertions, 49 deletions
diff --git a/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF b/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF index cccb166c8bd..5401227518e 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF @@ -68,10 +68,12 @@ Import-Package: com.google.common.cache;version="15.0.0", org.eclipse.osee.jaxrs, org.eclipse.osee.jaxrs.client, org.eclipse.osee.jaxrs.mvc, + org.eclipse.osee.jdbc, org.eclipse.osee.logger, org.eclipse.osgi.util, org.osgi.framework, org.osgi.service.http Bundle-Vendor: Eclipse Open System Engineering Environment -Export-Package: org.eclipse.osee.jaxrs.server.security +Export-Package: org.eclipse.osee.jaxrs.server.database, + org.eclipse.osee.jaxrs.server.security Bundle-ActivationPolicy: lazy diff --git a/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.security.oauth2.provider.server.xml b/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.security.oauth2.provider.server.xml index 3668840f6f2..122351ebeda 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.security.oauth2.provider.server.xml +++ b/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/jaxrs.security.oauth2.provider.server.xml @@ -6,5 +6,5 @@ <reference bind="setJaxRsResourceManager" cardinality="1..1" interface="org.eclipse.osee.jaxrs.server.internal.JaxRsResourceManager" name="JaxRsResourceManager" policy="static"/> <reference bind="setJaxRsAuthenticator" cardinality="1..1" interface="org.eclipse.osee.jaxrs.server.security.JaxRsAuthenticator" name="JaxRsAuthenticator" policy="static"/> <reference bind="setJaxRsOAuthStorage" cardinality="1..1" interface="org.eclipse.osee.jaxrs.server.security.JaxRsOAuthStorage" name="JaxRsOAuthStorage" policy="static"/> - <reference bind="setJaxRsSessionProvider" cardinality="0..1" interface="org.eclipse.osee.jaxrs.server.security.JaxRsSessionProvider" name="JaxRsSessionProvider" policy="static"/> + <reference bind="setJaxRsSessionProvider" cardinality="1..1" interface="org.eclipse.osee.jaxrs.server.security.JaxRsSessionProvider" name="JaxRsSessionProvider" policy="static"/> </scr:component> diff --git a/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/session.provider.xml b/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/session.provider.xml new file mode 100644 index 00000000000..6513435ec9a --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/OSGI-INF/session.provider.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" activate="start"> + <implementation class="org.eclipse.osee.jaxrs.server.session.JaxRsSessionProviderImpl"/> + <service> + <provide interface="org.eclipse.osee.jaxrs.server.security.JaxRsSessionProvider"/> + </service> + <reference bind="setLogger" cardinality="1..1" interface="org.eclipse.osee.logger.Log" name="Log" policy="static"/> + <reference bind="setJdbcService" cardinality="1..1" interface="org.eclipse.osee.jdbc.JdbcService" name="JdbcService" policy="static" target="(osgi.binding=oauth.jdbc.service)"/> +</scr:component> diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/database/AbstractDatabaseStorage.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/database/AbstractDatabaseStorage.java new file mode 100644 index 00000000000..871198b53fa --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/database/AbstractDatabaseStorage.java @@ -0,0 +1,208 @@ +/******************************************************************************* + * Copyright (c) 2014 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.database; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.Callable; +import org.eclipse.osee.framework.jdk.core.type.OseeCoreException; +import org.eclipse.osee.framework.jdk.core.type.ResultSet; +import org.eclipse.osee.framework.jdk.core.type.ResultSets; +import org.eclipse.osee.framework.jdk.core.util.Lib; +import org.eclipse.osee.jdbc.JdbcClient; +import org.eclipse.osee.jdbc.JdbcStatement; +import org.eclipse.osee.jdbc.SQL3DataType; +import org.eclipse.osee.logger.Log; + +/** + * @author Roberto E. Escobar + */ +public abstract class AbstractDatabaseStorage<T> { + + private final Log logger; + private final JdbcClient jdbcClient; + + public AbstractDatabaseStorage(Log logger, JdbcClient jdbcClient) { + super(); + this.logger = logger; + this.jdbcClient = jdbcClient; + } + + protected Object asVarcharOrNull(String value) { + return value != null ? value : SQL3DataType.VARCHAR; + } + + protected abstract Object[] asInsert(T item); + + protected abstract Object[] asUpdate(T item); + + protected abstract Object[] asDelete(T item); + + protected abstract T readData(JdbcStatement chStmt); + + protected <R> R execute(Callable<R> callable) { + try { + return callable.call(); + } catch (Exception ex) { + throw OseeCoreException.wrap(ex); + } + } + + protected T selectOneOrNull(final String query, final Object... data) { + return execute(select(query, data)).getOneOrNull(); + } + + protected ResultSet<T> selectItems(final String query, final Object... data) { + return execute(select(query, data)); + } + + protected void insertItems(final String insertSql, final T... items) { + insertItems(insertSql, Arrays.asList(items)); + } + + protected void insertItems(final String insertSql, final Iterable<T> items) { + execute(insert(insertSql, items)); + } + + protected void deleteItems(final String deleteSql, final T... items) { + deleteItems(deleteSql, Arrays.asList(items)); + } + + protected void deleteItems(final String deleteSql, final Iterable<T> items) { + execute(delete(deleteSql, items)); + } + + protected void updateItems(final String insertSql, final T... items) { + updateItems(insertSql, Arrays.asList(items)); + } + + protected void updateItems(final String updateSql, final Iterable<T> items) { + execute(update(updateSql, items)); + } + + protected long countItems(final String countSql, final Object... data) { + return execute(count(countSql, data)); + } + + private Callable<ResultSet<T>> select(final String query, final Object... data) { + return new AbstractCallable<Object[], ResultSet<T>>(query, data) { + + @Override + protected ResultSet<T> innerCall() throws Exception { + List<T> list = new LinkedList<>(); + JdbcStatement chStmt = jdbcClient.getStatement(); + try { + chStmt.runPreparedQuery(query, data); + while (chStmt.next()) { + T data = readData(chStmt); + list.add(data); + } + } finally { + chStmt.close(); + } + return ResultSets.newResultSet(list); + } + }; + } + + private Callable<Long> count(final String query, final Object... data) { + return new AbstractCallable<Object[], Long>(query, data) { + + @Override + protected Long innerCall() throws Exception { + return jdbcClient.runPreparedQueryFetchObject(-1L, query, data); + } + }; + } + + private Callable<Integer> insert(final String insertSql, final Iterable<T> items) { + return new AbstractCallable<Iterable<T>, Integer>(insertSql, items) { + + @Override + protected Integer innerCall() throws Exception { + List<Object[]> data = new ArrayList<>(); + for (T item : items) { + data.add(asInsert(item)); + } + return jdbcClient.runBatchUpdate(insertSql, data); + } + }; + } + + private Callable<Integer> delete(final String deleteSql, final Iterable<T> items) { + return new AbstractCallable<Iterable<T>, Integer>(deleteSql, items) { + + @Override + protected Integer innerCall() throws Exception { + List<Object[]> data = new ArrayList<>(); + for (T item : items) { + data.add(asDelete(item)); + } + return jdbcClient.runBatchUpdate(deleteSql, data); + } + }; + } + + private Callable<Integer> update(final String updateSql, final Iterable<T> items) { + return new AbstractCallable<Iterable<T>, Integer>(updateSql, items) { + + @Override + protected Integer innerCall() throws Exception { + List<Object[]> data = new ArrayList<>(); + for (T item : items) { + data.add(asUpdate(item)); + } + return jdbcClient.runBatchUpdate(updateSql, data); + } + }; + } + + protected abstract class AbstractCallable<I, O> implements Callable<O> { + + protected final String query; + protected final I data; + + public AbstractCallable(String query, I data) { + super(); + this.query = query; + this.data = data; + } + + protected JdbcClient getJdbcClient() { + return jdbcClient; + } + + @Override + public final O call() throws Exception { + long startTime = System.currentTimeMillis(); + long endTime = startTime; + O result = null; + try { + if (logger.isTraceEnabled()) { + logger.trace("%s [start] - [%s] [%s]", getClass().getSimpleName(), query, data); + } + result = innerCall(); + } finally { + endTime = System.currentTimeMillis() - startTime; + } + if (logger.isTraceEnabled()) { + logger.trace("%s [finished] - [%s] [%s] [%s]", getClass().getSimpleName(), Lib.asTimeString(endTime), query, + data); + } + return result; + } + + protected abstract O innerCall() throws Exception; + } + +}
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/OAuthUtil.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/OAuthUtil.java index 776cde53e06..398f760d93b 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/OAuthUtil.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/OAuthUtil.java @@ -130,11 +130,16 @@ public final class OAuthUtil { return finalRedirectURI; } - public static Response newAuthorizationRequiredResponse(URI redirectURI, boolean ignoreBasePath, String realmName, Message m, ContainerRequestContext context) { + public static Response newAuthorizationRequiredResponse(Exception ex, URI redirectURI, boolean ignoreBasePath, String realmName, Message m, ContainerRequestContext context) { HttpHeaders headers = new HttpHeadersImpl(m); if (redirectURI != null && JaxRsUtils.isHtmlSupported(headers.getAcceptableMediaTypes())) { URI finalRedirectURI = computeRedirectUri(redirectURI, ignoreBasePath, m, context); - return Response.temporaryRedirect(finalRedirectURI).build(); + ResponseBuilder toReturn = Response.temporaryRedirect(finalRedirectURI); + + if (ex != null) { + toReturn.entity("Incorrect Username/Password"); + } + return toReturn.build(); } else { ResponseBuilder builder = Response.status(Response.Status.UNAUTHORIZED); StringBuilder sb = new StringBuilder(); @@ -206,12 +211,18 @@ public final class OAuthUtil { } UserSubject data = new UserSubject(); data.setId(String.valueOf(subject.getGuid())); - data.setLogin(subject.getUserName()); + String userName = subject.getUserName(); + if (Strings.isValid(userName)) { + data.setLogin(subject.getUserName()); + } else { + data.setLogin(subject.getLogin()); + } data.setRoles(roles); Map<String, String> properties = new HashMap<>(); properties.put(SUBJECT_USERNAME, subject.getUserName()); String displayName = subject.getDisplayName(); + if (displayName.contains(",")) { String[] names = displayName.split(","); displayName = String.format("%s %s", names[1].trim(), names[0].trim()); diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2Configuration.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2Configuration.java index c92fcd77d00..f1733a36d5d 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2Configuration.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2Configuration.java @@ -34,8 +34,10 @@ public class OAuth2Configuration { public static final String OAUTH2_PROVIDER__ACCESS_TOKEN_EXPIRATION = qualify("access.token.expiration"); public static final String OAUTH2_PROVIDER__CODE_GRANT_EXPIRATION = qualify("code.grant.expiration"); public static final String OAUTH2_PROVIDER__REFRESH_TOKEN_EXPIRATION = qualify("refresh.token.expiration"); + public static final String OAUTH2_PROVIDER__SESSION_TOKEN_EXPIRATION = qualify("session.token.expiration"); public static final String OAUTH2_PROVIDER__NONCE_ALLOWED_WINDOW = qualify("nonce.allowed.window"); public static final String OAUTH2_PROVIDER__LOGIN_REDIRECT_URI = qualify("login.redirect.uri"); + public static final String OAUTH2_PROVIDER__LOGIN_REDIRECT_ERROR_URI = qualify("login.redirect.error.uri"); public static final String OAUTH2_PROVIDER__IGNORE_LOGIN_REDIRECT_BASE_PATH = qualify("ignore.login.redirect.base.path"); public static final String OAUTH2_PROVIDER__REALM = qualify("realm"); public static final String OAUTH2_PROVIDER__AUDIENCE_IS_ENDPOINT_ADDRESS = qualify("audience.is.endpoint.address"); @@ -60,9 +62,12 @@ public class OAuth2Configuration { public static final long DEFAULT_OAUTH2_PROVIDER__ACCESS_TOKEN_EXPIRATION = 10L * 60L * 1000L; public static final long DEFAULT_OAUTH2_PROVIDER__CODE_GRANT_EXPIRATION = 1L * 60L * 1000L; public static final long DEFAULT_OAUTH2_PROVIDER__REFRESH_TOKEN_EXPIRATION = 30L * 60L * 1000L; + public static final long DEFAULT_OAUTH2_PROVIDER__SESSION_TOKEN_EXPIRATION = 60L; public static final long DEFAULT_OAUTH2_PROVIDER__NONCE_ALLOWED_WINDOW = 2000L; public static final URI DEFAULT_OAUTH2_PROVIDER__LOGIN_REDIRECT_URI = null; public static final boolean DEFAULT_OAUTH2_PROVIDER__IGNORE_LOGIN_REDIRECT_BASE_PATH = false; + public static final URI DEFAULT_OAUTH2_PROVIDER__LOGIN_ERROR_REDIRECT_URI = null; + public static final boolean DEFAULT_OAUTH2_PROVIDER__IGNORE_LOGIN_ERROR_REDIRECT_BASE_PATH = false; public static final String DEFAULT_OAUTH2_PROVIDER__REALM = "OAuth2-OSEE"; public static final boolean DEFAULT_OAUTH2_PROVIDER__AUDIENCE_IS_ENDPOINT_ADDRESS = false; public static final boolean DEFAULT_OAUTH2_PROVIDER__BLOCK_UNSECURED_REQUESTS = false; @@ -99,6 +104,11 @@ public class OAuth2Configuration { return getBoolean(props, OAUTH2_PROVIDER__SERVICE_ENABLED, DEFAULT_OAUTH2_PROVIDER__SERVICE_ENABLED); } + public long getSessionTokenExpiration() { + return JaxRsUtils.getLong(props, OAUTH2_PROVIDER__SESSION_TOKEN_EXPIRATION, + DEFAULT_OAUTH2_PROVIDER__SESSION_TOKEN_EXPIRATION); + } + public long getAccessTokenExpiration() { return JaxRsUtils.getLong(props, OAUTH2_PROVIDER__ACCESS_TOKEN_EXPIRATION, DEFAULT_OAUTH2_PROVIDER__ACCESS_TOKEN_EXPIRATION); @@ -132,6 +142,19 @@ public class OAuth2Configuration { return loginRedirectURI; } + public URI getLoginRedirectErrorURI() { + URI loginRedirectErrorURI = DEFAULT_OAUTH2_PROVIDER__LOGIN_ERROR_REDIRECT_URI; + String value = get(props, OAUTH2_PROVIDER__LOGIN_REDIRECT_ERROR_URI, null); + if (Strings.isValid(value)) { + try { + loginRedirectErrorURI = new URI(value); + } catch (URISyntaxException ex) { + // do nothing; + } + } + return loginRedirectErrorURI; + } + public boolean isIgnoreLoginRedirectBasePath() { return getBoolean(props, OAUTH2_PROVIDER__IGNORE_LOGIN_REDIRECT_BASE_PATH, DEFAULT_OAUTH2_PROVIDER__IGNORE_LOGIN_REDIRECT_BASE_PATH); @@ -171,7 +194,8 @@ public class OAuth2Configuration { } public boolean isRefreshTokenAllowed() { - return getBoolean(props, OAUTH2_PROVIDER__REFRESH_TOKENS_ALLOWED, DEFAULT_OAUTH2_PROVIDER__REFRESH_TOKENS_ALLOWED); + return getBoolean(props, OAUTH2_PROVIDER__REFRESH_TOKENS_ALLOWED, + DEFAULT_OAUTH2_PROVIDER__REFRESH_TOKENS_ALLOWED); } public boolean isReportClientId() { diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java index 3c836068176..d6feaebe3e0 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java @@ -35,6 +35,7 @@ import org.eclipse.osee.jaxrs.server.security.JaxRsOAuthStorage; import org.eclipse.osee.jaxrs.server.security.OAuthCodeGrant; import org.eclipse.osee.jaxrs.server.security.OAuthToken; import org.eclipse.osee.jaxrs.server.security.OAuthTokenType; +import org.eclipse.osee.jaxrs.server.session.SessionData; /** * @author Roberto E. Escobar @@ -211,6 +212,10 @@ public class OAuth2DataProvider implements AuthorizationCodeDataProvider { return accessToken; } + public String createSessionToken(SessionData session) { + return serializer.encryptSessionToken(session, getSecretKey()); + } + @Override public ServerAccessToken getAccessToken(String accessToken) { return serializer.decryptAccessToken(this, accessToken, getSecretKey()); @@ -292,8 +297,8 @@ public class OAuth2DataProvider implements AuthorizationCodeDataProvider { @Override public ServerAccessToken getPreauthorizedToken(Client client, List<String> requestedScopes, UserSubject subject, String grantType) { - // This is an optimization useful in cases where a client requests an authorization code: - // if a user has already provided a given client with a pre-authorized token then challenging + // This is an optimization useful in cases where a client requests an authorization code: + // if a user has already provided a given client with a pre-authorized token then challenging // a user with yet another form asking for the authorization is redundant long clientId = getClientId(client); long subjectId = getSubjectId(subject); @@ -313,6 +318,8 @@ public class OAuth2DataProvider implements AuthorizationCodeDataProvider { if (!isExpired && entry.getGrantType().equals(grantType)) { token = serializer.decryptAccessToken(this, entry.getTokenKey(), getSecretKey()); + } else if (isExpired) { + revokeToken(client, entry.getTokenKey(), entry.getTokenType()); } break; } @@ -366,5 +373,4 @@ public class OAuth2DataProvider implements AuthorizationCodeDataProvider { private List<String> getApprovedScopes(List<String> requestedScopes, List<String> approvedScopes) { return approvedScopes.isEmpty() ? requestedScopes : approvedScopes; } - }
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2RequestFilter.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2RequestFilter.java index e034d62c5b7..db25a0c72a5 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2RequestFilter.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2RequestFilter.java @@ -48,6 +48,7 @@ public class OAuth2RequestFilter extends OAuthRequestFilter { private volatile boolean useUserSubject; private volatile URI redirectURI; + private volatile URI redirectErrorURI; private volatile boolean ignoreBasePath; public OAuth2RequestFilter(Log logger, JaxRsResourceManager resourceManager, SubjectProvider subjectProvider) { @@ -63,6 +64,10 @@ public class OAuth2RequestFilter extends OAuthRequestFilter { this.useUserSubject = useUserSubject; } + public void setRedirectErrorURI(URI redirectErrorURI) { + this.redirectErrorURI = redirectErrorURI; + } + public void setRedirectURI(URI redirectURI) { this.redirectURI = redirectURI; } @@ -133,12 +138,12 @@ public class OAuth2RequestFilter extends OAuthRequestFilter { private Response getAuthorizationRequired(Message msg, ContainerRequestContext context) { logger.debug("authorizationRequiredResponse called"); - return newAuthorizationRequiredResponse(redirectURI, ignoreBasePath, realm, msg, context); + return newAuthorizationRequiredResponse(null, redirectURI, ignoreBasePath, realm, msg, context); } private Response getAuthenticationException(Exception ex, Message msg, ContainerRequestContext context) { logger.error(ex, "Authorization error [%s]", msg.toString()); - return newAuthorizationRequiredResponse(redirectURI, ignoreBasePath, realm, msg, context); + return newAuthorizationRequiredResponse(ex, redirectErrorURI, ignoreBasePath, realm, msg, context); } private void doBasicAuthentication(MessageContext mc, String header) { diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2ServerProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2ServerProvider.java index 926ccb0db78..8e4aa04b368 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2ServerProvider.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2ServerProvider.java @@ -89,6 +89,7 @@ public class OAuth2ServerProvider { private JaxRsAuthenticator authenticator; private JaxRsSessionProvider sessionProvider; private JaxRsOAuthStorage storage; + private SubjectProvider subjectProvider; private final AtomicBoolean wasRegistered = new AtomicBoolean(); @@ -143,12 +144,12 @@ public class OAuth2ServerProvider { } private void initialize(OAuth2Configuration config) { - SubjectProvider subjectProvider = new SubjectProviderImpl(logger, sessionProvider, authenticator); + OAuthEncryption serializer = new OAuthEncryption(); + subjectProvider = new SubjectProviderImpl(logger, sessionProvider, authenticator, serializer); ClientProvider clientProvider = new ClientProviderImpl(subjectProvider, storage); audiences = Collections.emptyList(); - OAuthEncryption serializer = new OAuthEncryption(); dataProvider = new OAuth2DataProvider(clientProvider, subjectProvider, serializer, storage); filter = new OAuth2RequestFilter(logger, resourceManager, subjectProvider); @@ -230,6 +231,7 @@ public class OAuth2ServerProvider { private void configure(OAuth2Configuration config) { configure(config, filter); + configure(config, subjectProvider); configure(config, dataProvider); configure(config, nonceVerifier); @@ -256,6 +258,12 @@ public class OAuth2ServerProvider { configureObject(config, provider); } + private void configure(OAuth2Configuration config, SubjectProvider provider) { + provider.setSessionTokenExpiration(config.getSessionTokenExpiration()); + provider.setSecretKeyAlgorithm(config.getSecretKeyAlgorithm()); + provider.setSecretKeyEncoded(config.getEncodedSecretKey()); + } + private void configure(OAuth2Configuration config, NonceVerifier object) { if (object instanceof NonceVerifierImpl) { NonceVerifierImpl nonceVerifier = (NonceVerifierImpl) object; @@ -271,6 +279,8 @@ public class OAuth2ServerProvider { filter.setRealm(config.getRealm()); filter.setRedirectURI(config.getLoginRedirectURI()); + filter.setRedirectErrorURI(config.getLoginRedirectErrorURI()); + filter.setIgnoreBasePath(config.isIgnoreLoginRedirectBasePath()); filter.setRealm(config.getRealm()); configureObject(config, filter); diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/SubjectProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/SubjectProvider.java index eb121eab4c4..8ef5fa76cb2 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/SubjectProvider.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/SubjectProvider.java @@ -31,4 +31,9 @@ public interface SubjectProvider extends SessionAuthenticityTokenProvider, Subje UserSubject getSubjectById(long subjectId); + void setSecretKeyAlgorithm(String secretKeyAlgorithm); + + void setSecretKeyEncoded(String encodedSecretKey); + + void setSessionTokenExpiration(long accessTokenExpiration); }
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/OAuthEncryption.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/OAuthEncryption.java index 9808899936a..7ead0316a80 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/OAuthEncryption.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/OAuthEncryption.java @@ -27,6 +27,7 @@ import org.apache.cxf.rs.security.oauth2.tokens.refresh.RefreshToken; import org.apache.cxf.rs.security.oauth2.utils.crypto.CryptoUtils; import org.apache.cxf.rs.security.oauth2.utils.crypto.KeyProperties; import org.eclipse.osee.framework.jdk.core.util.Strings; +import org.eclipse.osee.jaxrs.server.session.SessionData; /** * @author Roberto E. Escobar @@ -86,6 +87,15 @@ public class OAuthEncryption { return state.toString(); } + public String encryptSessionToken(SessionData session, SecretKey secretKey) { + return encryptSessionToken(session, secretKey, null); + } + + private String encryptSessionToken(SessionData session, SecretKey secretKey, KeyProperties props) { + String tokenSequence = tokenizeSessionToken(session); + return CryptoUtils.encryptSequence(tokenSequence, secretKey, props); + } + public String encryptAccessToken(AccessToken token, SecretKey secretKey) { return encryptAccessToken(token, secretKey, null); } @@ -120,9 +130,8 @@ public class OAuthEncryption { private static ServerAuthorizationCodeGrant recreateCodeGrantInternal(OAuthDataProvider provider, String sequence) { String[] parts = getParts(sequence); - ServerAuthorizationCodeGrant grant = - new ServerAuthorizationCodeGrant(provider.getClient(parts[0]), parts[1], Long.valueOf(parts[2]), - Long.valueOf(parts[3])); + ServerAuthorizationCodeGrant grant = new ServerAuthorizationCodeGrant(provider.getClient(parts[0]), parts[1], + Long.valueOf(parts[2]), Long.valueOf(parts[3])); grant.setRedirectUri(getStringPart(parts[4])); grant.setAudience(getStringPart(parts[5])); grant.setClientCodeVerifier(getStringPart(parts[6])); @@ -174,6 +183,25 @@ public class OAuthEncryption { return sequence.split("\\" + SEP); } + public SessionData decryptSessionToken(String token, SecretKey secretKey) { + String decryptedSequence = CryptoUtils.decryptSequence(token, secretKey, null); + String[] parts = getParts(decryptedSequence); + + UserSubject recreateUserSubject = recreateUserSubject(parts[9]); + + SessionData toReturn = new SessionData(parts[0]); + toReturn.setAccountActive(Boolean.getBoolean(parts[1])); + toReturn.setExpiresIn(Long.valueOf(parts[2])); + toReturn.setIssuedAt(Long.valueOf(parts[3])); + toReturn.setAccountDisplayName(parts[4]); + toReturn.setAccountEmail(parts[5]); + toReturn.setAccountName(parts[6]); + toReturn.setAccountUsername(parts[7]); + toReturn.setAccountId(Long.valueOf(parts[8])); + toReturn.setSubject(recreateUserSubject); + return toReturn; + } + public ServerAccessToken decryptAccessToken(OAuthDataProvider provider, String token, SecretKey secretKey) { ServerAccessToken accessToken = decryptAccessToken(provider, token, secretKey, null); return accessToken; @@ -246,6 +274,41 @@ public class OAuthEncryption { return seq + SEP + token.getAccessTokens().toString(); } + private static String tokenizeSessionToken(SessionData session) { + StringBuilder state = new StringBuilder(); + // 0: key + state.append(tokenizeString(session.getGuid())); + // 1: active + state.append(SEP); + state.append(session.getAccountActive()); + // 2: expiresIn + state.append(SEP); + state.append(session.getExpiresIn()); + // 3: issuedAt + state.append(SEP); + state.append(session.getIssuedAt()); + // 4: display name + state.append(SEP); + state.append(tokenizeString(session.getAccountDisplayName())); + // 5: email + state.append(SEP); + state.append(tokenizeString(session.getAccountEmail())); + // 6: name + state.append(SEP); + state.append(tokenizeString(session.getAccountName())); + // 7: username + state.append(SEP); + state.append(tokenizeString(session.getAccountUsername())); + // 8: id + state.append(SEP); + state.append(session.getAccountId()); + // 9: user subject + state.append(SEP); + tokenizeUserSubject(state, session.getSubject()); + + return state.toString(); + } + private static String tokenizeServerToken(ServerAccessToken token) { StringBuilder state = new StringBuilder(); // 0: key @@ -253,7 +316,7 @@ public class OAuthEncryption { // 1: type state.append(SEP); state.append(tokenizeString(token.getTokenType())); - // 2: expiresIn + // 2: expiresIn state.append(SEP); state.append(token.getExpiresIn()); // 3: issuedAt diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/SubjectProviderImpl.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/SubjectProviderImpl.java index e8d55464b6b..253386911b6 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/SubjectProviderImpl.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/SubjectProviderImpl.java @@ -11,8 +11,15 @@ package org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters; import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.OAuthUtil.saveSecurityContext; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import java.util.UUID; +import javax.crypto.SecretKey; import javax.servlet.http.HttpSession; +import javax.ws.rs.core.Cookie; import javax.ws.rs.core.MultivaluedMap; import org.apache.cxf.jaxrs.ext.MessageContext; import org.apache.cxf.jaxrs.ext.MessageContextImpl; @@ -20,13 +27,16 @@ import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.rs.security.oauth2.common.UserSubject; import org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; import org.apache.cxf.security.SecurityContext; import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; import org.eclipse.osee.framework.jdk.core.util.Strings; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.OAuthUtil; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.SubjectProvider; +import org.eclipse.osee.jaxrs.server.internal.security.util.OseePrincipalImpl; import org.eclipse.osee.jaxrs.server.security.JaxRsAuthenticator; import org.eclipse.osee.jaxrs.server.security.JaxRsSessionProvider; +import org.eclipse.osee.jaxrs.server.session.SessionData; import org.eclipse.osee.logger.Log; /** @@ -39,12 +49,38 @@ public class SubjectProviderImpl implements SubjectProvider { private final Log logger; private final JaxRsAuthenticator authenticator; private final JaxRsSessionProvider sessionDelegate; + private final OAuthEncryption serializer; - public SubjectProviderImpl(Log logger, JaxRsSessionProvider sessionDelegate, JaxRsAuthenticator authenticator) { + private volatile SecretKey secretKey; + private String secretKeyEncoded; + private String secretKeyAlgorithm; + private long sessionTokenExpiration; + + public SubjectProviderImpl(Log logger, JaxRsSessionProvider sessionDelegate, JaxRsAuthenticator authenticator, OAuthEncryption serializer) { super(); this.logger = logger; this.sessionDelegate = sessionDelegate; this.authenticator = authenticator; + this.serializer = serializer; + } + + @Override + public void setSessionTokenExpiration(long sessionTokenExpiration) { + this.sessionTokenExpiration = sessionTokenExpiration; + } + + @Override + public void setSecretKeyEncoded(String secretKeyEncoded) { + this.secretKeyEncoded = secretKeyEncoded; + } + + @Override + public void setSecretKeyAlgorithm(String secretKeyAlgorithm) { + this.secretKeyAlgorithm = secretKeyAlgorithm; + } + + public long getSessionTokenExpiration() { + return sessionTokenExpiration; } @Override @@ -57,56 +93,66 @@ public class SubjectProviderImpl implements SubjectProvider { return OAuthUtil.getDisplayName(subject); } + private SecretKey getSecretKey() { + if (secretKey == null) { + secretKey = serializer.decodeSecretKey(secretKeyEncoded, secretKeyAlgorithm); + } + return secretKey; + } + + // Create Authenticity Session Token @Override public String createSessionToken(MessageContext mc, MultivaluedMap<String, String> params, UserSubject subject) { logger.debug("Create Session Token - subject[%s]", subject); - String sessionToken = null; + String sessionAuthenticityToken = null; if (sessionDelegate != null) { Long subjectId = OAuthUtil.getUserSubjectUuid(subject); - sessionToken = sessionDelegate.createSessionToken(subjectId); + sessionAuthenticityToken = sessionDelegate.createAuthenticitySessionToken(subjectId); } else { HttpSession session = mc.getHttpServletRequest().getSession(); - sessionToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); - if (!Strings.isValid(sessionToken)) { - sessionToken = UUID.randomUUID().toString(); - session.setAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, sessionToken); + sessionAuthenticityToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); + if (!Strings.isValid(sessionAuthenticityToken)) { + sessionAuthenticityToken = UUID.randomUUID().toString(); + session.setAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, sessionAuthenticityToken); } } - return sessionToken; + return sessionAuthenticityToken; } + // Doesn't seem to get called, removeSessionAuthenticityToken is used to retrieve the token @Override public String getSessionToken(MessageContext mc, MultivaluedMap<String, String> params, UserSubject subject) { logger.debug("Get Session Token - subject[%s]", subject); - String sessionToken = null; + String sessionAuthenticityToken = null; if (sessionDelegate != null) { Long subjectId = OAuthUtil.getUserSubjectUuid(subject); - sessionToken = sessionDelegate.getSessionToken(subjectId); + sessionAuthenticityToken = sessionDelegate.getSessionAuthenticityToken(subjectId); } else { HttpSession session = mc.getHttpServletRequest().getSession(); - sessionToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); + sessionAuthenticityToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); } - return sessionToken; + return sessionAuthenticityToken; } + // Get and remove Authenticity Session Token @Override public String removeSessionToken(MessageContext mc, MultivaluedMap<String, String> params, UserSubject subject) { logger.debug("Remove Session Token - subject[%s]", subject); - String sessionToken = null; + String sessionAuthenticityToken = null; if (sessionDelegate != null) { Long subjectId = OAuthUtil.getUserSubjectUuid(subject); - sessionToken = sessionDelegate.removeSessionToken(subjectId); + sessionAuthenticityToken = sessionDelegate.removeSessionAuthenticityToken(subjectId); } else { HttpSession session = mc.getHttpServletRequest().getSession(); - sessionToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); - if (sessionToken != null) { + sessionAuthenticityToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); + if (sessionAuthenticityToken != null) { session.removeAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); } } - return sessionToken; + return sessionAuthenticityToken; } @Override @@ -123,23 +169,55 @@ public class SubjectProviderImpl implements SubjectProvider { public SecurityContext getSecurityContextFromSession(MessageContext mc) { SecurityContext securityContext = null; if (sessionDelegate != null) { - // Add security context resolution through session delegate + Map<String, Cookie> cookies = mc.getHttpHeaders().getCookies(); + for (String cookieName : cookies.keySet()) { + Cookie cookie = cookies.get(cookieName); + if (cookie.getName().equalsIgnoreCase("JSESSIONID")) { + SessionData session = sessionDelegate.getSession(cookie.getValue()); + if (session != null) { + boolean isExpired = OAuthUtils.isExpired(session.getIssuedAt(), session.getExpiresIn()); + if (isExpired) { + sessionDelegate.removeSession(session.getGuid()); + } else { + securityContext = recreateSecurityContext(session); + } + } + break; + } + } } else { HttpSession session = mc.getHttpServletRequest().getSession(false); if (session != null) { securityContext = (SecurityContext) session.getAttribute(SESSION_SECURITY_CONTEXT); } } + saveSecurityContext(mc, securityContext); return securityContext; } + private SecurityContext recreateSecurityContext(SessionData sessionData) { + SessionData decryptSessionToken = serializer.decryptSessionToken(sessionData.getSubjectToken(), getSecretKey()); + UserSubject subject = decryptSessionToken.getSubject(); + Set<String> roles = new HashSet<>(); + roles.addAll(subject.getRoles()); + OseePrincipal principal = new OseePrincipalImpl(decryptSessionToken.getAccountId(), + decryptSessionToken.getAccountDisplayName(), decryptSessionToken.getAccountEmail(), subject.getLogin(), + sessionData.getAccountName(), decryptSessionToken.getAccountUsername(), decryptSessionToken.getAccountActive(), + true, roles, subject.getProperties()); + + return OAuthUtil.newSecurityContext(principal); + } + @Override public void authenticate(MessageContext mc, String scheme, String username, String password) { OseePrincipal principal = authenticate(scheme, username, password); SecurityContext securityContext = OAuthUtil.newSecurityContext(principal); if (sessionDelegate != null) { - // Add security context resolution through session delegate + HttpSession session = mc.getHttpServletRequest().getSession(true); + SessionData sessionData = httpSessionToSessionData(session, securityContext); + sessionDelegate.storeSession(sessionData); + session.setAttribute(SESSION_SECURITY_CONTEXT, securityContext); } else { HttpSession session = mc.getHttpServletRequest().getSession(true); session.setAttribute(SESSION_SECURITY_CONTEXT, securityContext); @@ -147,6 +225,34 @@ public class SubjectProviderImpl implements SubjectProvider { saveSecurityContext(mc, securityContext); } + private SessionData httpSessionToSessionData(HttpSession session, SecurityContext securitContext) { + OseePrincipal principal = (OseePrincipal) securitContext.getUserPrincipal(); + SessionData toReturn = new SessionData(session.getId()); + + UserSubject subject = new UserSubject(); + subject.setId(principal.getOseeGuid()); + subject.setLogin(principal.getLogin()); + subject.setProperties(principal.getProperties()); + List<String> roles = new ArrayList<>(); + roles.addAll(principal.getRoles()); + subject.setRoles(roles); + toReturn.setSubject(subject); + + toReturn.setAccountActive(principal.isActive()); + toReturn.setAccountDisplayName(principal.getDisplayName()); + toReturn.setAccountEmail(principal.getEmailAddress()); + toReturn.setAccountId(principal.getGuid()); + toReturn.setAccountName(principal.getName()); + toReturn.setAccountUsername(principal.getUserName()); + + toReturn.setIssuedAt(OAuthUtils.getIssuedAt()); + toReturn.setExpiresIn(getSessionTokenExpiration()); + + String token = serializer.encryptSessionToken(toReturn, getSecretKey()); + toReturn.setSubjectToken(token); + return toReturn; + } + @Override public UserSubject createSubject(String username, String password) { OseePrincipal principal = authenticate(OAuthConstants.BASIC_SCHEME, username, password); @@ -180,14 +286,6 @@ public class SubjectProviderImpl implements SubjectProvider { } } - long subjectId2 = getSubjectId(subject); - if (subjectId2 != subjectId) { - if (sessionDelegate != null) { - OseePrincipal principal = sessionDelegate.getSubjectById(subjectId); - subject = OAuthUtil.newUserSubject(principal); - } - } return subject; } - }
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ImplicitGrantEndpoint.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ImplicitGrantEndpoint.java index 40e0cdcce0b..7b5a09ef0bc 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ImplicitGrantEndpoint.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ImplicitGrantEndpoint.java @@ -64,6 +64,30 @@ public class ImplicitGrantEndpoint extends ImplicitGrantService { return response; } + @Override + protected Response createErrorResponse(MultivaluedMap<String, String> params, String redirectUri, String error) { + Response response = super.createErrorResponse(params, redirectUri, error); + + String forwardedServer = OAuthUtil.getForwarderServer(); + + if (Strings.isValid(forwardedServer)) { + URI location = response.getLocation(); + String scheme = location.getScheme(); + + URI finalUri = UriBuilder// + .fromPath(forwardedServer)// + .scheme(scheme)// + .path(location.getRawPath())// + .replaceQuery(location.getRawQuery())// + .fragment(location.getRawFragment())// + .buildFromEncoded(); + + response = Response.seeOther(finalUri).build(); + } + + return response; + } + /** * If a client does not include a redirect_uri parameter but has an exactly one pre-registered redirect_uri then use * that redirect_uri @@ -82,14 +106,46 @@ public class ImplicitGrantEndpoint extends ImplicitGrantService { @Override protected OAuthAuthorizationData createAuthorizationData(Client client, MultivaluedMap<String, String> params, UserSubject subject, String redirectUri, List<OAuthPermission> perms) { OAuthAuthorizationData secData = super.createAuthorizationData(client, params, subject, redirectUri, perms); + + String oldReplyTo = secData.getReplyTo(); + URI replyToUri = UriBuilder.fromPath(oldReplyTo).buildFromEncoded(); + + String forwardedServer = OAuthUtil.getForwarderServer(); + + if (Strings.isValid(forwardedServer)) { + String scheme = replyToUri.getScheme(); + + URI newReplyTo = UriBuilder// + .fromPath(forwardedServer)// + .scheme(scheme)// + .path(replyToUri.getRawPath())// + .replaceQuery(replyToUri.getRawQuery())// + .fragment(replyToUri.getRawFragment())// + .buildFromEncoded(); + + secData.setReplyTo(newReplyTo.toString()); + } + secData.setApplicationName(client.getApplicationName()); secData.setApplicationCertificates(client.getApplicationCertificates()); UriInfo uriInfo = getMessageContext().getUriInfo(); URI clientLogoUri = clientLogoUriResolver.getClientLogoUri(uriInfo, client); - String applicationLogoUri = clientLogoUri.toASCIIString(); - secData.setApplicationLogoUri(applicationLogoUri); + if (Strings.isValid(forwardedServer)) { + String scheme = clientLogoUri.getScheme(); + + URI newClientLogoUri = UriBuilder// + .fromPath(forwardedServer)// + .scheme(scheme)// + .path(clientLogoUri.getRawPath())// + .replaceQuery(clientLogoUri.getRawQuery())// + .fragment(clientLogoUri.getRawFragment())// + .buildFromEncoded(); + + secData.setApplicationLogoUri(newClientLogoUri.toString()); + } + return secData; } diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsSessionProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsSessionProvider.java index 09c49771759..4de3e0be594 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsSessionProvider.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsSessionProvider.java @@ -10,18 +10,28 @@ *******************************************************************************/ package org.eclipse.osee.jaxrs.server.security; +import javax.servlet.http.HttpSession; import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; +import org.eclipse.osee.jaxrs.server.session.SessionData; /** * @author Roberto E. Escobar */ public interface JaxRsSessionProvider { - String createSessionToken(Long subjectId); + String createAuthenticitySessionToken(Long subjectId); - String removeSessionToken(Long subjectId); + void storeSession(SessionData session); - String getSessionToken(Long subjectId); + String removeSessionAuthenticityToken(Long subjectId); + + String getSessionAuthenticityToken(Long subjectId); + + SessionData getSession(String sessionId); + + SessionData removeSession(String sessionId); + + HttpSession getSession(); OseePrincipal getSubjectById(Long subjectId); diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/AuthenticitySessionStorage.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/AuthenticitySessionStorage.java new file mode 100644 index 00000000000..efdc2585224 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/AuthenticitySessionStorage.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2015 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.session; + +import org.eclipse.osee.jaxrs.server.database.AbstractDatabaseStorage; +import org.eclipse.osee.jdbc.JdbcClient; +import org.eclipse.osee.jdbc.JdbcStatement; +import org.eclipse.osee.logger.Log; + +/** + * @author Angel Avila + */ +public class AuthenticitySessionStorage extends AbstractDatabaseStorage<AuthenticityToken> { + private static final String INSERT_AUTHENTICITY = + "INSERT INTO osee_oauth_authenticity_token (subject_id, token) VALUES (?,?)"; + + private static final String SELECT_AUTHENTICTY_BY_ID = + "select * from osee_oauth_authenticity_token where subject_id = ?"; + + private static final String DELETE_TOKEN_BY_ID = "DELETE FROM osee_oauth_authenticity_token WHERE subject_id = ?"; + + public AuthenticitySessionStorage(Log logger, JdbcClient jdbcClient) { + super(logger, jdbcClient); + } + + public void insertAuthenticityTokens(AuthenticityToken... sessions) { + insertItems(INSERT_AUTHENTICITY, sessions); + } + + public AuthenticityToken getSession(Long subjectId) { + return selectOneOrNull(SELECT_AUTHENTICTY_BY_ID, subjectId); + } + + @Override + protected Object[] asInsert(AuthenticityToken data) { + return new Object[] {data.getSubjectId(), data.getToken()}; + } + + @Override + protected Object[] asUpdate(AuthenticityToken data) { + return null; + } + + public void removeAuthenticitySessionTokens(Iterable<AuthenticityToken> datas) { + deleteItems(DELETE_TOKEN_BY_ID, datas); + } + + @Override + protected Object[] asDelete(AuthenticityToken data) { + return new Object[] {data.getSubjectId()}; + } + + @Override + protected AuthenticityToken readData(JdbcStatement chStmt) { + final Long subjectId = chStmt.getLong("subject_id"); + final String token = chStmt.getString("token"); + + AuthenticityToken authenticityToken = new AuthenticityToken(); + authenticityToken.setSubjectId(subjectId); + authenticityToken.setToken(token); + return authenticityToken; + } +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/AuthenticityToken.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/AuthenticityToken.java new file mode 100644 index 00000000000..c8841518e91 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/AuthenticityToken.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2015 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.session; + +/** + * @author Angel Avila + */ +public class AuthenticityToken { + + private Long subjectId; + private String token; + + public AuthenticityToken() { + } + + public Long getSubjectId() { + return subjectId; + } + + public String getToken() { + return token; + } + + public void setSubjectId(Long subjectId) { + this.subjectId = subjectId; + } + + public void setToken(String token) { + this.token = token; + } +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/JaxRsSessionProviderImpl.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/JaxRsSessionProviderImpl.java new file mode 100644 index 00000000000..e616ea42216 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/JaxRsSessionProviderImpl.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2015 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.session; + +import java.util.Collections; +import java.util.UUID; +import javax.servlet.http.HttpSession; +import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; +import org.eclipse.osee.framework.jdk.core.util.Strings; +import org.eclipse.osee.jaxrs.server.security.JaxRsSessionProvider; +import org.eclipse.osee.jdbc.JdbcClient; +import org.eclipse.osee.jdbc.JdbcService; +import org.eclipse.osee.logger.Log; + +/** + * @author Angel Avila + */ +public class JaxRsSessionProviderImpl implements JaxRsSessionProvider { + + private AuthenticitySessionStorage authenticitySessionStorage; + private SessionStorage sessionStorage; + private Log logger; + private JdbcClient jdbcClient; + + public JaxRsSessionProviderImpl() { + + } + + public void setLogger(Log logger) { + this.logger = logger; + } + + public void setJdbcService(JdbcService jdbcService) { + JdbcClient jdbcClient = jdbcService.getClient(); + this.jdbcClient = jdbcClient; + } + + public void start() { + authenticitySessionStorage = new AuthenticitySessionStorage(logger, jdbcClient); + sessionStorage = new SessionStorage(logger, jdbcClient); + } + + @Override + public String createAuthenticitySessionToken(Long subjectId) { + String token = getSessionAuthenticityToken(subjectId); + + if (Strings.isValid(token)) { + authenticitySessionStorage.removeAuthenticitySessionTokens( + Collections.singletonList(authenticitySessionStorage.getSession(subjectId))); + } + + AuthenticityToken authenticityToken = new AuthenticityToken(); + token = UUID.randomUUID().toString(); + authenticityToken.setSubjectId(subjectId); + authenticityToken.setToken(token); + authenticitySessionStorage.insertAuthenticityTokens(authenticityToken); + + return token; + } + + @Override + public String removeSessionAuthenticityToken(Long subjectId) { + String toReturn = ""; + + AuthenticityToken authenticityToken = authenticitySessionStorage.getSession(subjectId); + if (authenticityToken != null) { + authenticitySessionStorage.removeAuthenticitySessionTokens(Collections.singletonList(authenticityToken)); + toReturn = authenticityToken.getToken(); + } + return toReturn; + } + + @Override + public String getSessionAuthenticityToken(Long subjectId) { + AuthenticityToken authenticityToken = authenticitySessionStorage.getSession(subjectId); + return authenticityToken == null ? "" : authenticityToken.getToken(); + } + + @Override + public OseePrincipal getSubjectById(Long subjectId) { + return null; + } + + @Override + public HttpSession getSession() { + return null; + } + + @Override + public void storeSession(SessionData session) { + sessionStorage.insertSessions(session); + } + + @Override + public SessionData getSession(String sessionId) { + return sessionStorage.getSession(sessionId); + } + + @Override + public SessionData removeSession(String sessionId) { + SessionData session = sessionStorage.getSession(sessionId); + if (session != null) { + sessionStorage.deleteSessioin(Collections.singletonList(session)); + } + return session; + } + +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/SessionData.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/SessionData.java new file mode 100644 index 00000000000..0b6a83f205a --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/SessionData.java @@ -0,0 +1,116 @@ +/******************************************************************************* + * Copyright (c) 2015 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.session; + +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.eclipse.osee.framework.jdk.core.type.BaseIdentity; + +/** + * @author Angel Avila + */ +public class SessionData extends BaseIdentity<String> { + + private UserSubject subject; + private Long issuedAt; + private Long expiresIn; + private String subjectToken; + private String accountName; + private String accountUsername; + private Long accountId; + private String accountDisplayName; + private String accountEmail; + private boolean accountActive; + + public SessionData(String id) { + super(id); + } + + public UserSubject getSubject() { + return subject; + } + + public Long getIssuedAt() { + return issuedAt; + } + + public Long getExpiresIn() { + return expiresIn; + } + + public String getSubjectToken() { + return subjectToken; + } + + public String getAccountName() { + return accountName; + } + + public String getAccountUsername() { + return accountUsername; + } + + public Long getAccountId() { + return accountId; + } + + public String getAccountDisplayName() { + return accountDisplayName; + } + + public String getAccountEmail() { + return accountEmail; + } + + public boolean getAccountActive() { + return accountActive; + } + + public void setSubject(UserSubject subject) { + this.subject = subject; + } + + public void setIssuedAt(Long issuedAt) { + this.issuedAt = issuedAt; + } + + public void setExpiresIn(Long expiresIn) { + this.expiresIn = expiresIn; + } + + public void setSubjectToken(String subjectToken) { + this.subjectToken = subjectToken; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public void setAccountUsername(String accountUsername) { + this.accountUsername = accountUsername; + } + + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + + public void setAccountDisplayName(String accountDisplayName) { + this.accountDisplayName = accountDisplayName; + } + + public void setAccountEmail(String accountEmail) { + this.accountEmail = accountEmail; + } + + public void setAccountActive(boolean accountActive) { + this.accountActive = accountActive; + } + +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/SessionStorage.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/SessionStorage.java new file mode 100644 index 00000000000..303f0caa596 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/session/SessionStorage.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2015 Boeing. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Boeing - initial API and implementation + *******************************************************************************/ +package org.eclipse.osee.jaxrs.server.session; + +import org.eclipse.osee.jaxrs.server.database.AbstractDatabaseStorage; +import org.eclipse.osee.jdbc.JdbcClient; +import org.eclipse.osee.jdbc.JdbcStatement; +import org.eclipse.osee.logger.Log; + +/** + * @author Angel Avila + */ +public class SessionStorage extends AbstractDatabaseStorage<SessionData> { + + private static final String INSERT_SESSION = + "INSERT INTO osee_oauth_session (session_id, issued_at, expires_in, subject_token) VALUES (?,?,?,?)"; + + private static final String SELECT_SESSION_BY_ID = "select * from osee_oauth_session where session_id = ?"; + + private static final String DELETE_SESSION_BY_ID = "DELETE FROM osee_oauth_session WHERE session_id = ?"; + + public SessionStorage(Log logger, JdbcClient jdbcClient) { + super(logger, jdbcClient); + } + + @Override + protected Object[] asInsert(SessionData session) { + return new Object[] {session.getGuid(), session.getIssuedAt(), session.getExpiresIn(), session.getSubjectToken()}; + } + + @Override + protected Object[] asUpdate(SessionData item) { + return null; + } + + @Override + protected Object[] asDelete(SessionData item) { + return new Object[] {item.getGuid()}; + } + + public void insertSessions(SessionData... sessions) { + insertItems(INSERT_SESSION, sessions); + } + + public SessionData getSession(String sessionId) { + return selectOneOrNull(SELECT_SESSION_BY_ID, sessionId); + } + + public void deleteSessioin(Iterable<SessionData> datas) { + deleteItems(DELETE_SESSION_BY_ID, datas); + } + + @Override + protected SessionData readData(JdbcStatement chStmt) { + final String sessionId = chStmt.getString("session_id"); + final Long issuedAt = chStmt.getLong("issued_at"); + final Long expiresIn = chStmt.getLong("expires_in"); + final String subjectToken = chStmt.getString("subject_token"); + + SessionData sessionData = new SessionData(sessionId); + sessionData.setIssuedAt(issuedAt); + sessionData.setExpiresIn(expiresIn); + sessionData.setSubjectToken(subjectToken); + + return sessionData; + } +} |