diff options
author | Roberto E. Escobar | 2014-08-07 00:40:44 +0000 |
---|---|---|
committer | Roberto E. Escobar | 2014-09-29 22:55:14 +0000 |
commit | e204273d599623d491a84cc1f9b08b126ef76a27 (patch) | |
tree | ecff4366153201a9e4ef3aa26a557b371fb62b57 /plugins/org.eclipse.osee.jaxrs.server | |
parent | 947d8a5a9b3da405cf2a3d538ad1b4091aaee8d1 (diff) | |
download | org.eclipse.osee-e204273d599623d491a84cc1f9b08b126ef76a27.tar.gz org.eclipse.osee-e204273d599623d491a84cc1f9b08b126ef76a27.tar.xz org.eclipse.osee-e204273d599623d491a84cc1f9b08b126ef76a27.zip |
feature[ats_ATS64254]: Create OAuth2 Client Registration API
Change-Id: I126b531f1fbeff674a443f6aa340120c90097108
Diffstat (limited to 'plugins/org.eclipse.osee.jaxrs.server')
29 files changed, 1597 insertions, 112 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 a6a6f4c27c0..631e6b8f57a 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.osee.jaxrs.server/META-INF/MANIFEST.MF @@ -18,13 +18,16 @@ Import-Package: com.google.common.cache, javax.ws.rs.core;version="2.0.0", javax.ws.rs.ext;version="2.0.0", org.apache.cxf;version="3.0.0", + org.apache.cxf.attachment;version="3.0.0", org.apache.cxf.binding;version="3.0.0", org.apache.cxf.common.security;version="3.0.0", org.apache.cxf.common.util;version="3.0.0", org.apache.cxf.endpoint;version="3.0.0", org.apache.cxf.feature;version="3.0.0", + org.apache.cxf.helpers;version="3.0.0", org.apache.cxf.interceptor;version="3.0.0", org.apache.cxf.interceptor.security;version="3.0.0", + org.apache.cxf.io;version="3.0.0", org.apache.cxf.jaxrs;version="3.0.0", org.apache.cxf.jaxrs.ext;version="3.0.0", org.apache.cxf.jaxrs.ext.multipart;version="3.0.0", diff --git a/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/authorize_form.html b/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/authorize_form.html index 5d0786152e6..143d51de3cc 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/authorize_form.html +++ b/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/authorize_form.html @@ -10,7 +10,7 @@ <div class="container"> <h1>OSEE - OAuth2 Authorization</h1> <div class="media"> - <a class="pull-left" href="<?applicationWebUri?>"><img class="media-object" alt="Logo" src="<?applicationLogoUri?>" /></a> + <a class="pull-left" href="<?applicationWebUri?>"><img class="media-object img-thumbnail img-responsive" alt="Logo" src="<?applicationLogoUri?>" style="height: 120px; width: 120px;" /></a> <div class="media-body"> <h3 class="media-heading"> <?applicationName?> diff --git a/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/client_registration.html b/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/client_registration.html new file mode 100644 index 00000000000..d7f66e997ba --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/client_registration.html @@ -0,0 +1,28 @@ +<!DOCTYPE HTML> +<html lang="en"> +<head> +<link rel="stylesheet" href="/lib/css/bootstrap.min.css"> +<meta name="viewport" content="width=device-width, initial-scale=1"></meta> +<meta charset="UTF-8"> +<title>OSEE - OAuth2 Client Registration Confirmation</title> +</head> +<body> + <div class="container"> + <h1>OSEE - OAuth2 Client Registration Confirmation</h1> + <p> + Please use the provided Client Identifier and Shared Secret when requesting information from + <b><?resourceServerName?></b> server as part of OAuth flows. + </p> + <dl class="dl-horizontal"> + <dt>Client Identifier:</dt> + <dd> + <?clientId?> + </dd> + <dt>Client Secret:</dt> + <dd> + <?clientSecret?> + </dd> + </dl> + </div> +</body> +</html>
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/client_registration_form.html b/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/client_registration_form.html new file mode 100644 index 00000000000..95532f4bbb7 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/OSEE-INF/templates/client_registration_form.html @@ -0,0 +1,96 @@ +<!DOCTYPE HTML> +<html lang="en"> +<head> +<link rel="stylesheet" href="/lib/css/bootstrap.min.css"> +<meta name="viewport" content="width=device-width, initial-scale=1"></meta> +<meta charset="UTF-8"> +<title>OSEE - OAuth2 Client Registration</title> +<script type="text/javascript"> + function reloadImageURL() { + var inputElement = document.getElementById('applicationLogo'); + readImageURL(inputElement); + } + + function readImageURL(input) { + if (input.files && input.files[0]) { + var file = input.files[0]; + + var reader = new FileReader(); + reader.onload = function(e) { + var element = document.getElementById('image-preview'); + element.src = e.target.result; + }; + reader.readAsDataURL(file); + } + } +</script> +</head> +<body onload="reloadImageURL()"> + <div class="container"> + <h1>OSEE - OAuth2 Client Registration</h1> + <form class="form-horizontal" role="form" method="POST" enctype="multipart/form-data" action="<?replyTo?>"> + <?hiddenFieldsSection?> + + <div class="form-group"> + <label class="col-sm-2 control-label" for="applicationName">Application Name</label> + <div class="col-sm-10"> + <input type="text" class="form-control" name="applicationName" placeholder="Application name" + title="The name entered is used to identify your application to end users." required> + </div> + </div> + + <div class="form-group"> + <label class="col-sm-2 control-label" for="applicationDescription">Description</label> + <div class="col-sm-10"> + <input type="text" class="form-control" name="applicationDescription" placeholder="Application description" + title="The description name entered is used to description the application to end users." required> + </div> + </div> + + <div class="form-group"> + <div class="col-sm-2 control-label"> + <label for="applicationUri">Homepage URL</label> <span class="help-block">Optional</span> + </div> + <div class="col-sm-10"> + <input type="url" class="form-control" name="applicationUri" placeholder="http:// or https://" + title="The URL entered is used to allow end users to access your application's home page."> + </div> + </div> + + <div class="form-group"> + <div class="col-sm-2 control-label"> + <label for="applicationLogoData">Logo</label> <span class="help-block">Optional</span> + </div> + <div class="col-sm-10"> + <input type="file" accept="image/gif,image/jpeg,image/png" id="applicationLogoData" name="applicationLogoData" placeholder="Application Logo" + title="Select an image to use as the application logo" onchange="readImageURL(this)"> + <div class="media help-block"> + <img id="image-preview" class="media-object pull-left img-thumbnail img-responsive" alt="Selected-Logo" + style="height: 120px; width: 120px;" /> + <p class="media-body"> + This is how your logo will look like to end users.<br />Max size: 120 x 120 px + </p> + </div> + </div> + </div> + + <div class="form-group"> + <div class="col-sm-2 control-label"> + <label for="applicationRedirectUri">Authorized redirect URI</label> <span class="help-block">Optional</span> + </div> + <div class="col-sm-10" + title="Enter the authorized callback URI's separated by spaces or newlines. These URI's are provided by client applications during OAuth flows."> + <textarea class="form-control" rows="3" name="applicationRedirectUri" placeholder="https://www.example.com/oauth2callback"></textarea> + </div> + </div> + + <div class="form-group"> + <div class="col-sm-10 pull-right"> + <button type="submit" class="btn btn-default" name="<?registrationDecisionKey?>" value="<?registrationDecisionCancel?>">Cancel</button> + <button type="submit" class="btn btn-primary" name="<?registrationDecisionKey?>" value="<?registrationDecisionAccept?>">Register</button> + </div> + </div> + </form> + </div> +</body> +</html>
\ 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 72f42cbf522..7b360b2d2c4 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 @@ -12,11 +12,13 @@ package org.eclipse.osee.jaxrs.server.internal.security.oauth2; import java.io.UnsupportedEncodingException; import java.net.URI; +import java.security.Principal; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.concurrent.TimeUnit; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; @@ -30,6 +32,7 @@ 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.AuthorizationUtils; import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.apache.cxf.security.LoginSecurityContext; import org.apache.cxf.security.SecurityContext; import org.eclipse.osee.framework.jdk.core.type.BaseIdentity; import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; @@ -190,6 +193,20 @@ public final class OAuthUtil { return toReturn; } + public static UserSubject newSubject(SecurityContext securityContext) { + Principal principal = securityContext.getUserPrincipal(); + String name = principal != null ? principal.getName() : "UNKNOWN"; + List<String> roleNames = Collections.emptyList(); + if (securityContext instanceof LoginSecurityContext) { + roleNames = new ArrayList<String>(); + Set<Principal> roles = ((LoginSecurityContext) securityContext).getUserRoles(); + for (Principal p : roles) { + roleNames.add(p.getName()); + } + } + return new UserSubject(name, roleNames); + } + private static final class UserSubjectWrapper extends BaseIdentity<Long> implements OseePrincipal { private final UserSubject subject; diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/ClientLogoUriResolver.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/ClientLogoUriResolver.java new file mode 100644 index 00000000000..01f12650f6c --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/ClientLogoUriResolver.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider; + +import java.net.URI; +import javax.ws.rs.core.UriInfo; +import org.apache.cxf.rs.security.oauth2.common.Client; + +/** + * @author Roberto E. Escobar + */ +public interface ClientLogoUriResolver { + + URI getClientLogoUri(UriInfo uriInfo, Client client); + +}
\ 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/ClientProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/ClientProvider.java index 297af4e7ab2..ac351880532 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/ClientProvider.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/ClientProvider.java @@ -10,17 +10,24 @@ *******************************************************************************/ package org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider; +import java.io.InputStream; +import javax.ws.rs.core.UriInfo; import org.apache.cxf.rs.security.oauth2.common.Client; +import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientFormData; +import com.google.common.io.InputSupplier; /** * @author Roberto E. Escobar */ -public interface ClientProvider { +public interface ClientProvider extends ClientLogoUriResolver { + + long getClientId(Client client); Client getClient(String clientId); - Client createClient(); + Client createClient(UriInfo uriInfo, OseePrincipal principal, ClientFormData data); - long getClientId(Client client); + InputSupplier<InputStream> getClientLogoSupplier(UriInfo uriInfo, String applicationGuid); }
\ 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/OAuth2DataProvider.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/OAuth2DataProvider.java index 40fdf644e3d..224cdff6eec 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 @@ -121,7 +121,12 @@ public class OAuth2DataProvider implements AuthorizationCodeDataProvider { @Override public Client getClient(String clientId) { - return clientProvider.getClient(clientId); + Client client = clientProvider.getClient(clientId); + if (client == null) { + OAuthError error = new OAuthError(OAuthConstants.INVALID_CLIENT, "Client Id not found."); + throw new OAuthServiceException(error); + } + return client; } @Override @@ -295,7 +300,7 @@ public class OAuth2DataProvider implements AuthorizationCodeDataProvider { OAuthToken accessToken = storage.getPreauthorizedToken(clientId, subjectId, grantType); ServerAccessToken token = null; - if (accessToken != null) { + if (accessToken != null && accessToken.getType() != OAuthTokenType.REFRESH_TOKEN && accessToken.getType() != OAuthTokenType.UNKNOW_TOKEN) { token = serializer.decryptAccessToken(this, accessToken.getTokenKey(), getSecretKey()); } return token; 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 e7eda3ca552..3e6140268b3 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 @@ -44,11 +44,17 @@ import org.apache.cxf.rs.security.oauth2.tokens.hawk.NonceVerifier; import org.apache.cxf.rs.security.oauth2.tokens.hawk.NonceVerifierImpl; import org.eclipse.osee.jaxrs.server.internal.JaxRsConstants; import org.eclipse.osee.jaxrs.server.internal.applications.JaxRsApplicationRegistry; -import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.CxfAuthorizationCodeService; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.ClientProviderImpl; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.OAuthEncryption; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.adapters.SubjectProviderImpl; -import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientRegistrationService; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.AbstractClientService; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.AuthorizationCodeEndpoint; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientEndpoint; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientRegistrationEndpoint; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ImplicitGrantEndpoint; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.writers.AuthorizationDataHtmlWriter; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.writers.ClientRegistrationDataHtmlWriter; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.writers.ClientRegistrationResponseHtmlWriter; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.writers.OOBAuthorizationResponseHtmlWriter; import org.eclipse.osee.jaxrs.server.security.JaxRsAuthenticator; import org.eclipse.osee.jaxrs.server.security.JaxRsOAuth; @@ -131,8 +137,8 @@ public class OAuth2ServerProvider { } private void initialize(OAuth2Configuration config) { - ClientProvider clientProvider = null; SubjectProvider subjectProvider = new SubjectProviderImpl(logger, sessionProvider, authenticator); + ClientProvider clientProvider = new ClientProviderImpl(subjectProvider, storage); audiences = Collections.emptyList(); @@ -147,16 +153,19 @@ public class OAuth2ServerProvider { endpoints.add(bind(new TokenRevocationService(), dataProvider)); //@formatter:off - endpoints.add(bind(new CxfAuthorizationCodeService(), dataProvider, subjectProvider)); - endpoints.add(bind(new ImplicitGrantService(), dataProvider, subjectProvider)); + endpoints.add(bind(new AuthorizationCodeEndpoint(clientProvider), dataProvider, subjectProvider)); + endpoints.add(bind(new ImplicitGrantEndpoint(clientProvider), dataProvider, subjectProvider)); //@formatter:on endpoints.add(bind(new AccessTokenValidatorService(), dataProvider)); - endpoints.add(bind(new ClientRegistrationService(), clientProvider)); + endpoints.add(bind(new ClientRegistrationEndpoint(logger), clientProvider, subjectProvider)); + endpoints.add(bind(new ClientEndpoint(logger), clientProvider, subjectProvider)); // Add OAuth2 application local Writers endpoints.add(new AuthorizationDataHtmlWriter()); endpoints.add(new OOBAuthorizationResponseHtmlWriter()); + endpoints.add(new ClientRegistrationDataHtmlWriter()); + endpoints.add(new ClientRegistrationResponseHtmlWriter()); application = new OAuth2Application(endpoints); @@ -314,10 +323,18 @@ public class OAuth2ServerProvider { accessTokenService.setAudiences(audiences); accessTokenService.setGrantHandlers(grantHandlers); } + + if (object instanceof AbstractClientService) { + AbstractClientService clientService = (AbstractClientService) object; + clientService.setBlockUnsecureRequests(config.isBlockUnsecureRequests()); + } } - private static ClientRegistrationService bind(ClientRegistrationService object, ClientProvider dataProvider) { + private static AbstractClientService bind(AbstractClientService object, ClientProvider dataProvider, SubjectProvider subjectProvider) { object.setDataProvider(dataProvider); + object.setResourceOwnerNameProvider(subjectProvider); + object.setSessionAuthenticityTokenProvider(subjectProvider); + object.setSubjectCreator(subjectProvider); return object; } 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 d141b5e2c1c..51aa63bc139 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 @@ -29,4 +29,5 @@ public interface SubjectProvider extends SessionAuthenticityTokenProvider, Subje SecurityContext getSecurityContextFromSession(MessageContext mc); + UserSubject getSubjectById(long subjectId); }
\ 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/ApplicationClient.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/ApplicationClient.java new file mode 100644 index 00000000000..f47437bcf23 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/ApplicationClient.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.adapters; + +import java.io.InputStream; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.eclipse.osee.framework.jdk.core.type.Identity; +import org.eclipse.osee.jaxrs.server.security.OAuthClient; +import com.google.common.io.InputSupplier; + +/** + * @author Roberto E. Escobar + */ +public class ApplicationClient extends Client implements OAuthClient { + + private static final long serialVersionUID = -5666467776236248089L; + + private final long clientUuid; + private final long subjectId; + private final String guid; + private InputSupplier<InputStream> logoSupplier; + + public ApplicationClient(long clientUuid, long subjectId, String guid) { + super(); + this.clientUuid = clientUuid; + this.subjectId = subjectId; + this.guid = guid; + } + + @Override + public long getClientUuid() { + return clientUuid; + } + + @Override + public long getSubjectId() { + return subjectId; + } + + @Override + public String getGuid() { + return guid; + } + + @Override + public boolean matches(Identity<?>... identities) { + for (Identity<?> identity : identities) { + if (equals(identity)) { + return true; + } + } + return false; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((guid == null) ? 0 : guid.hashCode()); + return result; + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + boolean equal = false; + if (obj instanceof Identity) { + Identity<String> identity = (Identity<String>) obj; + if (getGuid() == identity.getGuid()) { + equal = true; + } else if (getGuid() != null) { + equal = getGuid().equals(identity.getGuid()); + } + } + return equal; + } + + @Override + public boolean hasApplicationLogoSupplier() { + return logoSupplier != null; + } + + @Override + public InputSupplier<InputStream> getApplicationLogoSupplier() { + return logoSupplier; + } + + public void setApplicationLogoSupplier(InputSupplier<InputStream> logoSupplier) { + this.logoSupplier = logoSupplier; + } + +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/ClientProviderImpl.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/ClientProviderImpl.java new file mode 100644 index 00000000000..84921906575 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/ClientProviderImpl.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.adapters; + +import java.io.BufferedInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URL; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import org.apache.cxf.helpers.IOUtils; +import org.apache.cxf.io.CachedOutputStream; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.utils.OAuthUtils; +import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; +import org.eclipse.osee.framework.jdk.core.util.Lib; +import org.eclipse.osee.framework.jdk.core.util.Strings; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.ClientProvider; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.SubjectProvider; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientFormData; +import org.eclipse.osee.jaxrs.server.security.JaxRsOAuthStorage; +import org.eclipse.osee.jaxrs.server.security.OAuthClient; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.google.common.io.InputSupplier; + +/** + * @author Roberto E. Escobar + */ +public class ClientProviderImpl implements ClientProvider { + + private static final int MAX_LOGOS = 10; + private static final long EVICT_AFTER_30_MINS = 30L * 60L * 1000L; + + private final LoadingCache<String, CachedOutputStream> logosCache; + private final SubjectProvider subjectProvider; + private final JaxRsOAuthStorage storage; + + public ClientProviderImpl(SubjectProvider subjectProvider, JaxRsOAuthStorage storage) { + super(); + this.subjectProvider = subjectProvider; + this.storage = storage; + this.logosCache = newLogoCache(MAX_LOGOS, EVICT_AFTER_30_MINS); + } + + @Override + public long getClientId(Client client) { + long clientUuid = -1; + if (client instanceof ApplicationClient) { + ApplicationClient appClient = (ApplicationClient) client; + clientUuid = appClient.getClientUuid(); + } else { + String clientKey = client.getClientId(); + clientUuid = storage.getClientUuidByKey(clientKey); + } + return clientUuid; + } + + @Override + public Client getClient(String clientId) { + OAuthClient data = storage.getClientByClientKey(clientId); + + ApplicationClient client = null; + if (data != null) { + UserSubject subject = subjectProvider.getSubjectById(data.getSubjectId()); + + client = new ApplicationClient(data.getClientUuid(), data.getSubjectId(), data.getGuid()); + client.setSubject(subject); + client.setApplicationName(data.getApplicationName()); + client.setApplicationDescription(data.getApplicationDescription()); + client.setApplicationWebUri(data.getApplicationWebUri()); + client.setProperties(data.getProperties()); + client.setConfidential(data.isConfidential()); + + client.setClientId(data.getClientId()); + client.setClientSecret(data.getClientSecret()); + + client.setRegisteredAudiences(data.getRegisteredAudiences()); + client.setAllowedGrantTypes(data.getAllowedGrantTypes()); + client.setRegisteredScopes(data.getRegisteredScopes()); + client.setRedirectUris(data.getRedirectUris()); + client.setApplicationCertificates(data.getApplicationCertificates()); + client.setApplicationLogoUri(data.getApplicationLogoUri()); + client.setApplicationLogoSupplier(data.getApplicationLogoSupplier()); + } + return client; + } + + @Override + public Client createClient(UriInfo uriInfo, OseePrincipal principal, final ClientFormData data) { + String guid = data.getGuid(); + long clientUuid = Lib.generateUuid(); + long subjectId = subjectProvider.getSubjectId(data.getUserSubject()); + + ApplicationClient client = new ApplicationClient(clientUuid, subjectId, guid); + client.setSubject(data.getUserSubject()); + client.setApplicationName(data.getName()); + client.setApplicationDescription(data.getDescription()); + client.setApplicationWebUri(data.getWebUri()); + client.setProperties(data.getProperties()); + client.setConfidential(data.isConfidential()); + + /** + * generate credentials + */ + String clientId = OAuthUtils.generateRandomTokenKey(); + client.setClientId(clientId); + + if (client.isConfidential()) { + String clientSecret = OAuthUtils.generateRandomTokenKey(); + client.setClientSecret(clientSecret); + } + + /** + * <pre> + * Additional Security options: + * - restrict resource server + * - restrict allowed grant types + * - register allowed scopes/permissions + * - restrict redirect/callback URIs + * - authenticate using certificate + * </pre> + */ + client.setRegisteredAudiences(data.getAllowedAudiences()); + client.setAllowedGrantTypes(data.getAllowedGrantTypes()); + client.setRegisteredScopes(data.getAllowedScopes()); + client.setRedirectUris(data.getRedirectUris()); + client.setApplicationCertificates(data.getCertificates()); + client.setApplicationLogoUri(data.getLogoUri()); + if (data.isLogoAvailable()) { + InputSupplier<InputStream> logoSupplier = new InputSupplier<InputStream>() { + @Override + public InputStream getInput() { + return data.getLogoContent(); + } + }; + client.setApplicationLogoSupplier(logoSupplier); + } + storage.storeClient(principal, client); + return client; + } + + @Override + public URI getClientLogoUri(UriInfo uriInfo, Client client) { + String clientGuid; + if (client instanceof ApplicationClient) { + ApplicationClient appClient = (ApplicationClient) client; + clientGuid = appClient.getGuid(); + } else { + OAuthClient authClient = storage.getClientByClientKey(client.getClientId()); + clientGuid = authClient.getGuid(); + } + return UriBuilder.fromUri(uriInfo.getBaseUri()).path("client").path("{client-guid}").path("logo").build( + clientGuid); + } + + @Override + public InputSupplier<InputStream> getClientLogoSupplier(UriInfo uriInfo, String applicationGuid) { + OAuthClient client = storage.getClientByClientGuid(applicationGuid); + InputSupplier<InputStream> supplier = null; + if (client.hasApplicationLogoSupplier()) { + supplier = client.getApplicationLogoSupplier(); + } else { + String logoUri = client.getApplicationLogoUri(); + if (Strings.isValid(logoUri)) { + supplier = newSupplier(logoUri); + } else { + // provide default image if available; + } + } + return supplier; + } + + private InputSupplier<InputStream> newSupplier(final String uri) { + return new InputSupplier<InputStream>() { + + @Override + public InputStream getInput() throws IOException { + CachedOutputStream cos; + try { + cos = logosCache.get(uri); + } catch (ExecutionException ex) { + throw new IOException(ex); + } + return cos.getInputStream(); + } + }; + } + + private static LoadingCache<String, CachedOutputStream> newLogoCache(int cacheMaxSize, long cacheEvictTimeoutMillis) { + return newCache(new CacheLoader<String, CachedOutputStream>() { + + @Override + public CachedOutputStream load(String uri) throws Exception { + CachedOutputStream cos = new CachedOutputStream(); + InputStream inputStream = null; + try { + URL url = new URL(uri); + inputStream = new BufferedInputStream(url.openStream()); + IOUtils.copy(inputStream, cos); + } finally { + Lib.close(inputStream); + } + return cos; + } + + }, cacheMaxSize, cacheEvictTimeoutMillis); + } + + private static <K, V> LoadingCache<K, V> newCache(CacheLoader<K, V> loader, int cacheMaxSize, long cacheEvictTimeoutMillis) { + return CacheBuilder.newBuilder()// + .maximumSize(cacheMaxSize)// + .expireAfterWrite(cacheEvictTimeoutMillis, TimeUnit.MILLISECONDS)// + .build(loader); + } +}
\ 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/CxfAuthorizationCodeService.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/CxfAuthorizationCodeService.java deleted file mode 100644 index b8b0574aba2..00000000000 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/CxfAuthorizationCodeService.java +++ /dev/null @@ -1,49 +0,0 @@ -/******************************************************************************* - * 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.internal.security.oauth2.provider.adapters; - -import javax.ws.rs.core.Response; -import org.apache.cxf.rs.security.oauth2.common.Client; -import org.apache.cxf.rs.security.oauth2.common.OOBAuthorizationResponse; -import org.apache.cxf.rs.security.oauth2.provider.OOBResponseDeliverer; -import org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService; - -/** - * @author Roberto E. Escobar - */ -public class CxfAuthorizationCodeService extends AuthorizationCodeGrantService { - - private boolean canSupportPublicClients; - private OOBResponseDeliverer oobDeliverer; - - @Override - protected Response deliverOOBResponse(OOBAuthorizationResponse response) { - if (oobDeliverer != null) { - return oobDeliverer.deliver(response); - } else { - return Response.ok(response).build(); - } - } - - @Override - protected boolean canSupportPublicClient(Client c) { - return canSupportPublicClients && !c.isConfidential() && c.getClientSecret() == null; - } - - @Override - public void setCanSupportPublicClients(boolean support) { - this.canSupportPublicClients = support; - } - - public void setOobDeliverer(OOBResponseDeliverer oobDeliverer) { - this.oobDeliverer = oobDeliverer; - } -}
\ 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/SubjectProviderImpl.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/adapters/SubjectProviderImpl.java index 493f086cf41..b5fc34348e0 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 @@ -14,10 +14,11 @@ import java.util.UUID; import javax.servlet.http.HttpSession; import javax.ws.rs.core.MultivaluedMap; import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.ext.MessageContextImpl; +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.util.Strings; import org.eclipse.osee.jaxrs.server.internal.security.oauth2.OAuthUtil; @@ -112,7 +113,7 @@ public class SubjectProviderImpl implements SubjectProvider { UserSubject subject = mc.getContent(UserSubject.class); if (subject == null) { SecurityContext securityContext = getSecurityContext(mc); - subject = OAuthUtils.createSubject(securityContext); + subject = OAuthUtil.newSubject(securityContext); } return subject; } @@ -121,8 +122,7 @@ public class SubjectProviderImpl implements SubjectProvider { public SecurityContext getSecurityContextFromSession(MessageContext mc) { SecurityContext securityContext = null; if (sessionDelegate != null) { - // Long subjectId = OAuthUtil.getUserSubjectUuid(subject); - // sessionDelegate.getSecurityContext(subjectId); + // Add security context resolution through session delegate } else { HttpSession session = mc.getHttpServletRequest().getSession(false); if (session != null) { @@ -139,8 +139,7 @@ public class SubjectProviderImpl implements SubjectProvider { SecurityContext securityContext = OAuthUtil.newSecurityContext(subject); if (sessionDelegate != null) { - // Long subjectId = OAuthUtil.getUserSubjectUuid(subject); - // sessionDelegate.storeSecurityContext(subjectId, sc); + // Add security context resolution through session delegate } else { HttpSession session = mc.getHttpServletRequest().getSession(true); session.setAttribute(SESSION_SECURITY_CONTEXT, securityContext); @@ -177,4 +176,25 @@ public class SubjectProviderImpl implements SubjectProvider { mc.put(SecurityContext.class.getName(), securityContext); } } + + @Override + public UserSubject getSubjectById(long subjectId) { + MessageContext mc = new MessageContextImpl(PhaseInterceptorChain.getCurrentMessage()); + UserSubject subject = mc.getContent(UserSubject.class); + if (subject == null) { + SecurityContext securityContext = getSecurityContext(mc); + if (securityContext != null) { + subject = OAuthUtil.newSubject(securityContext); + } + } + + long subjectId2 = getSubjectId(subject); + if (subjectId2 != subjectId) { + if (sessionDelegate != null) { + Subject user = sessionDelegate.getSubjectById(subjectId); + subject = OAuthUtil.newUserSubject(user); + } + } + 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/AbstractClientService.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/AbstractClientService.java new file mode 100644 index 00000000000..d867fae4092 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/AbstractClientService.java @@ -0,0 +1,158 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import java.util.UUID; +import javax.servlet.http.HttpSession; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import org.apache.cxf.jaxrs.ext.MessageContext; +import org.apache.cxf.jaxrs.utils.ExceptionUtils; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.provider.ResourceOwnerNameProvider; +import org.apache.cxf.rs.security.oauth2.provider.SessionAuthenticityTokenProvider; +import org.apache.cxf.rs.security.oauth2.provider.SubjectCreator; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.apache.cxf.security.SecurityContext; +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.ClientProvider; +import org.eclipse.osee.logger.Log; + +/** + * @author Roberto E. Escobar + */ +public abstract class AbstractClientService { + + private MessageContext mc; + private final Log logger; + private ClientProvider provider; + + private boolean blockUnsecureRequests; + private SessionAuthenticityTokenProvider sessionAuthenticityTokenProvider; + private SubjectCreator subjectCreator; + private ResourceOwnerNameProvider resourceOwnerNameProvider; + + public AbstractClientService(Log logger) { + this.logger = logger; + } + + public void setDataProvider(ClientProvider provider) { + this.provider = provider; + } + + public void setResourceOwnerNameProvider(ResourceOwnerNameProvider resourceOwnerNameProvider) { + this.resourceOwnerNameProvider = resourceOwnerNameProvider; + } + + public void setSessionAuthenticityTokenProvider(SessionAuthenticityTokenProvider sessionAuthenticityTokenProvider) { + this.sessionAuthenticityTokenProvider = sessionAuthenticityTokenProvider; + } + + public void setSubjectCreator(SubjectCreator creator) { + this.subjectCreator = creator; + } + + public void setBlockUnsecureRequests(boolean blockUnsecureRequests) { + this.blockUnsecureRequests = blockUnsecureRequests; + } + + @Context + public void setMessageContext(MessageContext context) { + this.mc = context; + } + + public MessageContext getMessageContext() { + return mc; + } + + protected ClientProvider getDataProvider() { + return provider; + } + + protected UserSubject createUserSubject(SecurityContext securityContext) { + UserSubject subject = null; + if (subjectCreator != null) { + subject = subjectCreator.createUserSubject(getMessageContext()); + if (subject != null) { + return subject; + } + } + + subject = getMessageContext().getContent(UserSubject.class); + if (subject != null) { + return subject; + } else { + return OAuthUtil.newSubject(securityContext); + } + } + + protected SecurityContext getAndValidateSecurityContext() { + MessageContext mc = getMessageContext(); + + SecurityContext securityContext = (SecurityContext) mc.get(SecurityContext.class); + if (securityContext == null) { + securityContext = (SecurityContext) mc.get(SecurityContext.class.getName()); + } + if (securityContext == null || securityContext.getUserPrincipal() == null) { + throw ExceptionUtils.toNotAuthorizedException(null, null); + } + checkTransportSecurity(); + return securityContext; + } + + protected void checkTransportSecurity() { + if (!mc.getSecurityContext().isSecure()) { + logger.warn("Unsecure HTTP, Transport Layer Security is recommended"); + if (blockUnsecureRequests) { + throw ExceptionUtils.toBadRequestException(null, null); + } + } + } + + protected void personalizeData(ClientRegistrationData data, UserSubject userSubject) { + if (resourceOwnerNameProvider != null) { + data.setEndUserName(resourceOwnerNameProvider.getName(userSubject)); + } + } + + protected void addAuthenticityTokenToSession(ClientRegistrationData data, MultivaluedMap<String, String> params, UserSubject subject) { + String sessionToken; + if (sessionAuthenticityTokenProvider != null) { + sessionToken = sessionAuthenticityTokenProvider.createSessionToken(getMessageContext(), params, subject); + } 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); + } + } + data.setAuthenticityToken(sessionToken); + } + + protected boolean compareRequestAndSessionTokens(String requestToken, UserSubject subject) { + MessageContext mc = getMessageContext(); + String sessionToken; + if (sessionAuthenticityTokenProvider != null) { + sessionToken = + sessionAuthenticityTokenProvider.removeSessionToken(mc, mc.getHttpHeaders().getRequestHeaders(), subject); + } else { + HttpSession session = mc.getHttpServletRequest().getSession(); + sessionToken = (String) session.getAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); + if (sessionToken != null) { + session.removeAttribute(OAuthConstants.SESSION_AUTHENTICITY_TOKEN); + } + } + return !Strings.isValid(sessionToken) ? false : sessionToken.equals(requestToken); + } + +}
\ 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/AuthorizationCodeEndpoint.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/AuthorizationCodeEndpoint.java new file mode 100644 index 00000000000..6a6f8a35f81 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/AuthorizationCodeEndpoint.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import java.net.URI; +import java.util.List; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData; +import org.apache.cxf.rs.security.oauth2.common.OAuthPermission; +import org.apache.cxf.rs.security.oauth2.common.OOBAuthorizationResponse; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.provider.OOBResponseDeliverer; +import org.apache.cxf.rs.security.oauth2.services.AuthorizationCodeGrantService; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.ClientLogoUriResolver; + +/** + * @author Roberto E. Escobar + */ +public class AuthorizationCodeEndpoint extends AuthorizationCodeGrantService { + + private boolean canSupportPublicClients; + private OOBResponseDeliverer oobDeliverer; + + private final ClientLogoUriResolver clientLogoUriResolver; + + public AuthorizationCodeEndpoint(ClientLogoUriResolver clientLogoUriResolver) { + super(); + this.clientLogoUriResolver = clientLogoUriResolver; + } + + @Override + protected Response deliverOOBResponse(OOBAuthorizationResponse response) { + if (oobDeliverer != null) { + return oobDeliverer.deliver(response); + } else { + return Response.ok(response).build(); + } + } + + /** + * <pre> + * Extra security features: + * - only confidential clients should have a client secret + * - if they are not confidential they should not have a client secret. + * + * If desired, add the following: + * && !c.isConfidential() && c.getClientSecret() == null + * </pre> + */ + @Override + protected boolean canSupportPublicClient(Client c) { + return canSupportPublicClients; + } + + @Override + public void setCanSupportPublicClients(boolean support) { + this.canSupportPublicClients = support; + } + + public void setOobDeliverer(OOBResponseDeliverer oobDeliverer) { + this.oobDeliverer = oobDeliverer; + } + + /** + * Override fixes OAuthAuthorizationData creation + */ + @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); + 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); + + return secData; + } +}
\ 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/ClientConstants.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientConstants.java new file mode 100644 index 00000000000..540979acc32 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientConstants.java @@ -0,0 +1,40 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +/** + * @author Roberto E. Escobar + */ +public final class ClientConstants { + + private ClientConstants() { + // Constants + } + + public static final String CLIENT_REGISTRATION__APPLICATION_GUID = "applicationGuid"; + public static final String CLIENT_REGISTRATION__APPLICATION_NAME = "applicationName"; + public static final String CLIENT_REGISTRATION__APPLICATION_DESCRIPTION = "applicationDescription"; + public static final String CLIENT_REGISTRATION__APPLICATION_URI = "applicationUri"; + public static final String CLIENT_REGISTRATION__APPLICATION_REDIRECT_URI = "applicationRedirectUri"; + public static final String CLIENT_REGISTRATION__APPLICATION_LOGO_DATA = "applicationLogoData"; + public static final String CLIENT_REGISTRATION__APPLICATION_LOGO_URI = "applicationLogoUri"; + + public static final String CLIENT_REGISTRATION__DECISION_KEY = "applicationRegistrationDecision"; + public static final String CLIENT_REGISTRATION__DECISION_CANCEL = "cancel"; + public static final String CLIENT_REGISTRATION__DECISION_REGISTER = "register"; + + public static final String CLIENT_REGISTRATION__IS_CONFIDENTIAL = "applicationConfidential"; + public static final String CLIENT_REGISTRATION__AUDIENCES = "applicationAllowedAudiences"; + public static final String CLIENT_REGISTRATION__ALLOWED_GRANT_TYPES = "applicationAllowedGrantTypes"; + public static final String CLIENT_REGISTRATION__ALLOWED_SCOPES = "applicationAllowedScopes"; + public static final String CLIENT_REGISTRATION__CERTIFICATE = "applicationCertificate"; + +}
\ 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/ClientEndpoint.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientEndpoint.java new file mode 100644 index 00000000000..4e4d75f8252 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientEndpoint.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; +import javax.ws.rs.core.UriInfo; +import org.eclipse.osee.framework.jdk.core.util.Lib; +import org.eclipse.osee.logger.Log; +import com.google.common.io.InputSupplier; + +/** + * @author Roberto E. Escobar + */ +@Path("/client") +public class ClientEndpoint extends AbstractClientService { + + public ClientEndpoint(Log logger) { + super(logger); + } + + @GET + @Path("{application-guid}/logo") + @Produces({"image/png", "image/jpeg", "image/gif"}) + public Response getApplicationLogo(@Context final UriInfo uriInfo, @PathParam("application-guid") final String applicationGuid) { + return Response.ok(new StreamingOutput() { + + @Override + public void write(OutputStream outputStream) throws IOException, WebApplicationException { + InputSupplier<InputStream> supplier = getDataProvider().getClientLogoSupplier(uriInfo, applicationGuid); + if (supplier != null) { + InputStream inputStream = null; + try { + inputStream = supplier.getInput(); + Lib.inputStreamToOutputStream(inputStream, outputStream); + } finally { + Lib.close(inputStream); + } + } + } + }).build(); + } +}
\ 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/ClientFormData.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientFormData.java new file mode 100644 index 00000000000..c57814439d8 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientFormData.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import java.io.InputStream; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.eclipse.osee.framework.jdk.core.type.BaseIdentity; +import org.eclipse.osee.framework.jdk.core.type.Named; + +/** + * @author Roberto E. Escobar + */ +public class ClientFormData extends BaseIdentity<String> implements Named { + + private UserSubject userSubject; + private String name; + private String description; + private String webUri; + private String logoUri; + private List<String> certificates = new LinkedList<String>(); + + private List<String> redirectUris; + + private InputStream logoContent; + private Map<String, String> logoParameters; + + private boolean isConfidential; + private List<String> allowedGrantTypes = new LinkedList<String>(); + private List<String> allowedScopes = new LinkedList<String>(); + private List<String> allowedAudiences = new LinkedList<String>(); + + private Map<String, String> properties = new HashMap<String, String>(); + + public ClientFormData(String id) { + super(id); + } + + public UserSubject getUserSubject() { + return userSubject; + } + + @Override + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public String getWebUri() { + return webUri; + } + + public List<String> getRedirectUris() { + return redirectUris; + } + + public InputStream getLogoContent() { + return logoContent; + } + + public Map<String, String> getLogoParameters() { + return logoParameters; + } + + public void setUserSubject(UserSubject userSubject) { + this.userSubject = userSubject; + } + + public void setName(String name) { + this.name = name; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setWebUri(String websiteUri) { + this.webUri = websiteUri; + } + + public void setRedirectUris(List<String> redirectUris) { + this.redirectUris = redirectUris; + } + + public void setLogoContent(InputStream logoContent) { + this.logoContent = logoContent; + } + + public void setLogoParameters(Map<String, String> logoParameters) { + this.logoParameters = logoParameters; + } + + public boolean isLogoAvailable() { + return logoContent != null; + } + + public List<String> getCertificates() { + return certificates; + } + + public boolean isConfidential() { + return isConfidential; + } + + public List<String> getAllowedGrantTypes() { + return allowedGrantTypes; + } + + public List<String> getAllowedScopes() { + return allowedScopes; + } + + public List<String> getAllowedAudiences() { + return allowedAudiences; + } + + public Map<String, String> getProperties() { + return properties; + } + + public void setCertificates(List<String> certificates) { + this.certificates = certificates; + } + + public void setConfidential(boolean isConfidential) { + this.isConfidential = isConfidential; + } + + public void setAllowedGrantTypes(List<String> allowedGrantTypes) { + this.allowedGrantTypes = allowedGrantTypes; + } + + public void setAllowedScopes(List<String> allowedScopes) { + this.allowedScopes = allowedScopes; + } + + public void setAllowedAudiences(List<String> allowedAudiences) { + this.allowedAudiences = allowedAudiences; + } + + public void setProperties(Map<String, String> properties) { + this.properties = properties; + } + + public String getLogoUri() { + return logoUri; + } + + public void setLogoUri(String logoUri) { + this.logoUri = logoUri; + } + +}
\ 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/ClientRegistrationData.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationData.java new file mode 100644 index 00000000000..aeecd66c6bf --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationData.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * @author Roberto E. Escobar + */ +@XmlRootElement +public class ClientRegistrationData { + + private String clientGuid; + private String replyTo; + private String authenticityToken; + private String endUserName; + + public String getClientGuid() { + return clientGuid; + } + + public String getReplyTo() { + return replyTo; + } + + public String getAuthenticityToken() { + return authenticityToken; + } + + public String getEndUserName() { + return endUserName; + } + + public void setClientGuid(String clientGuid) { + this.clientGuid = clientGuid; + } + + public void setReplyTo(String replyTo) { + this.replyTo = replyTo; + } + + public void setAuthenticityToken(String authenticityToken) { + this.authenticityToken = authenticityToken; + } + + public void setEndUserName(String endUserName) { + this.endUserName = endUserName; + } + +}
\ 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/ClientRegistrationEndpoint.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationEndpoint.java new file mode 100644 index 00000000000..1f6076338da --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationEndpoint.java @@ -0,0 +1,179 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__ALLOWED_GRANT_TYPES; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__ALLOWED_SCOPES; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_DESCRIPTION; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_GUID; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_LOGO_DATA; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_LOGO_URI; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_NAME; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_REDIRECT_URI; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_URI; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__AUDIENCES; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__CERTIFICATE; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__DECISION_KEY; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__DECISION_REGISTER; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__IS_CONFIDENTIAL; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import org.apache.cxf.jaxrs.ext.multipart.Attachment; +import org.apache.cxf.jaxrs.ext.multipart.ContentDisposition; +import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; +import org.apache.cxf.jaxrs.utils.ExceptionUtils; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.apache.cxf.security.SecurityContext; +import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; +import org.eclipse.osee.framework.jdk.core.util.GUID; +import org.eclipse.osee.framework.jdk.core.util.Strings; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.OAuthUtil; +import org.eclipse.osee.logger.Log; + +/** + * @author Roberto E. Escobar + */ +@Path("/client-registration") +public class ClientRegistrationEndpoint extends AbstractClientService { + + public ClientRegistrationEndpoint(Log logger) { + super(logger); + } + + @GET + @Produces({"text/html", "application/xml", "application/json"}) + public Response startRegistration(@Context UriInfo uriInfo, @Context HttpHeaders headers) { + SecurityContext sc = getAndValidateSecurityContext(); + UserSubject subject = createUserSubject(sc); + + ClientRegistrationData data = new ClientRegistrationData(); + addAuthenticityTokenToSession(data, headers.getRequestHeaders(), subject); + personalizeData(data, subject); + + String replyTo = UriBuilder.fromPath(uriInfo.getPath()).path("complete").build().toString(); + data.setClientGuid(GUID.create()); + data.setReplyTo(replyTo); + return Response.ok(data).build(); + } + + @POST + @Path("/complete") + @Consumes(MediaType.MULTIPART_FORM_DATA) + public Response finishRegistration(@Context UriInfo uriInfo, // + MultipartBody multiPart) { + SecurityContext securityContext = getAndValidateSecurityContext(); + UserSubject userSubject = createUserSubject(securityContext); + + // Make sure the session is valid + String sessionToken = multiPart.getAttachmentObject(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, String.class); + if (!compareRequestAndSessionTokens(sessionToken, userSubject)) { + throw ExceptionUtils.toBadRequestException(null, null); + } + + // Get the end user decision value + String decision = multiPart.getAttachmentObject(CLIENT_REGISTRATION__DECISION_KEY, String.class); + boolean registrationAllowed = CLIENT_REGISTRATION__DECISION_REGISTER.equals(decision); + + Response response = null; + if (registrationAllowed) { + response = register(uriInfo, userSubject, multiPart); + } else { + response = createCancellationResponse(multiPart); + } + return response; + } + + private Response register(UriInfo uriInfo, UserSubject userSubject, MultipartBody multiPart) { + String appGuid = multiPart.getAttachmentObject(CLIENT_REGISTRATION__APPLICATION_GUID, String.class); + String appName = multiPart.getAttachmentObject(CLIENT_REGISTRATION__APPLICATION_NAME, String.class); + String appDesc = multiPart.getAttachmentObject(CLIENT_REGISTRATION__APPLICATION_DESCRIPTION, String.class); + String appWebsite = multiPart.getAttachmentObject(CLIENT_REGISTRATION__APPLICATION_URI, String.class); + String appRedirects = multiPart.getAttachmentObject(CLIENT_REGISTRATION__APPLICATION_REDIRECT_URI, String.class); + String appConfidential = multiPart.getAttachmentObject(CLIENT_REGISTRATION__IS_CONFIDENTIAL, String.class); + String appAudiences = multiPart.getAttachmentObject(CLIENT_REGISTRATION__AUDIENCES, String.class); + String appGrantTypes = multiPart.getAttachmentObject(CLIENT_REGISTRATION__ALLOWED_GRANT_TYPES, String.class); + String appScopes = multiPart.getAttachmentObject(CLIENT_REGISTRATION__ALLOWED_SCOPES, String.class); + String appCertificate = multiPart.getAttachmentObject(CLIENT_REGISTRATION__CERTIFICATE, String.class); + String appLogoUri = multiPart.getAttachmentObject(CLIENT_REGISTRATION__APPLICATION_LOGO_URI, String.class); + + ClientFormData input = new ClientFormData(appGuid); + input.setUserSubject(userSubject); + input.setName(appName); + input.setDescription(appDesc); + input.setWebUri(appWebsite); + input.setRedirectUris(parseMultilined(appRedirects)); + input.setConfidential(parseConfidential(appConfidential)); + + input.setAllowedAudiences(parseMultilined(appAudiences)); + input.setAllowedGrantTypes(parseMultilined(appGrantTypes)); + input.setAllowedScopes(parseMultilined(appScopes)); + input.setCertificates(parseMultilined(appCertificate)); + input.setLogoUri(appLogoUri); + + Attachment att = multiPart.getAttachment(CLIENT_REGISTRATION__APPLICATION_LOGO_DATA); + if (att != null) { + InputStream logoContent = att.getObject(InputStream.class); + input.setLogoContent(logoContent); + + ContentDisposition cd = att.getContentDisposition(); + if (cd != null) { + input.setLogoParameters(cd.getParameters()); + } + } + OseePrincipal principal = OAuthUtil.newOseePrincipal(userSubject); + Client client = getDataProvider().createClient(uriInfo, principal, input); + + ClientRegistrationResponse data = new ClientRegistrationResponse(); + data.setClientId(client.getClientId()); + data.setClientSecret(client.getClientSecret()); + return Response.ok(data).build(); + } + + private Response createCancellationResponse(MultipartBody body) { + return Response.ok().build(); + } + + private boolean parseConfidential(String appConfidential) { + // For now all clients will be confidential - which will require them to submit their secret key + return true; + } + + private List<String> parseMultilined(String rawData) { + List<String> toReturn = Collections.emptyList(); + if (Strings.isValid(rawData)) { + toReturn = new ArrayList<String>(); + String[] entries = rawData.split("\\s+"); + for (String entry : entries) { + entry = entry.trim(); + if (Strings.isValid(entry)) { + toReturn.add(entry); + } + } + } + return toReturn; + } + +}
\ 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/ClientRegistrationResponse.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationResponse.java new file mode 100644 index 00000000000..e5d1bb55b5a --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationResponse.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import javax.xml.bind.annotation.XmlRootElement; + +/** + * @author Roberto E. Escobar + */ +@XmlRootElement +public class ClientRegistrationResponse { + + private String resourceServerName; + private String clientId; + private String clientSecret; + + public String getResourceServerName() { + return resourceServerName; + } + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public void setResourceServerName(String resourceServerName) { + this.resourceServerName = resourceServerName; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public void setClientSecret(String clientSecret) { + this.clientSecret = clientSecret; + } + +}
\ 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/ClientRegistrationService.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationService.java deleted file mode 100644 index abef6a2608e..00000000000 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ClientRegistrationService.java +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * 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.internal.security.oauth2.provider.endpoints; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.core.Response; -import org.apache.cxf.rs.security.oauth2.common.Client; -import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.ClientProvider; - -/** - * @author Roberto E. Escobar - */ -@Path("/clients") -public class ClientRegistrationService { - - private ClientProvider provider; - - public void setDataProvider(ClientProvider provider) { - this.provider = provider; - } - - @GET - public Response getClient() { - return Response.ok().build(); - } - - @Path("{client-id}") - @GET - public Response getClient(@PathParam("{client-id}") String clientId) { - Client client = provider.getClient(clientId); - return Response.ok(client).build(); - } - -}
\ 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 new file mode 100644 index 00000000000..00f2ada9e22 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/endpoints/ImplicitGrantEndpoint.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.endpoints; + +import java.net.URI; +import java.util.List; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriInfo; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.OAuthAuthorizationData; +import org.apache.cxf.rs.security.oauth2.common.OAuthPermission; +import org.apache.cxf.rs.security.oauth2.common.UserSubject; +import org.apache.cxf.rs.security.oauth2.services.ImplicitGrantService; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.ClientLogoUriResolver; + +/** + * @author Roberto E. Escobar + */ +public class ImplicitGrantEndpoint extends ImplicitGrantService { + + private final ClientLogoUriResolver clientLogoUriResolver; + + public ImplicitGrantEndpoint(ClientLogoUriResolver clientLogoUriResolver) { + super(); + this.clientLogoUriResolver = clientLogoUriResolver; + } + + /** + * Override fixes OAuthAuthorizationData creation + */ + @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); + 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); + return secData; + } + +}
\ 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/writers/ClientRegistrationDataHtmlWriter.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/writers/ClientRegistrationDataHtmlWriter.java new file mode 100644 index 00000000000..abc6e2d359a --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/writers/ClientRegistrationDataHtmlWriter.java @@ -0,0 +1,56 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.writers; + +import static org.eclipse.osee.jaxrs.server.internal.JaxRsUtils.asTemplateValue; +import static org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants.CLIENT_REGISTRATION__APPLICATION_GUID; +import javax.ws.rs.ext.Provider; +import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants; +import org.eclipse.osee.framework.jdk.core.type.ViewModel; +import org.eclipse.osee.jaxrs.server.internal.resources.AbstractHtmlWriter; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientConstants; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientRegistrationData; +import org.eclipse.osee.jaxrs.server.internal.security.util.HiddenFormFields; + +/** + * @author Roberto E. Escobar + */ +@Provider +public class ClientRegistrationDataHtmlWriter extends AbstractHtmlWriter<ClientRegistrationData> { + + //@formatter:off + private static final String CLIENT_REG_FORM__TEMPLATE = "client_registration_form.html"; + private static final String CLIENT_REG_FORM__REPLY_TO_TAG = "replyTo"; + private static final String CLIENT_REG_FORM__REGISTRATION_DECISION = "registrationDecisionKey"; + private static final String CLIENT_REG_FORM__REGISTRATION_DECISION_CANCEL = "registrationDecisionCancel"; + private static final String CLIENT_REG_FORM__REGISTRATION_DECISION_ACCEPT = "registrationDecisionAccept"; + private static final String CLIENT_REG_FORM__HIDDEN_FIELDS_SECTION_TAG = "hiddenFieldsSection"; + //@formatter:on + + @Override + public Class<ClientRegistrationData> getSupportedClass() { + return ClientRegistrationData.class; + } + + @Override + public ViewModel asViewModel(ClientRegistrationData data) { + ViewModel model = new ViewModel(CLIENT_REG_FORM__TEMPLATE); + model.param(CLIENT_REG_FORM__REPLY_TO_TAG, asTemplateValue(data.getReplyTo())); + model.param(CLIENT_REG_FORM__REGISTRATION_DECISION, ClientConstants.CLIENT_REGISTRATION__DECISION_KEY); + model.param(CLIENT_REG_FORM__REGISTRATION_DECISION_ACCEPT, ClientConstants.CLIENT_REGISTRATION__DECISION_REGISTER); + model.param(CLIENT_REG_FORM__REGISTRATION_DECISION_CANCEL, ClientConstants.CLIENT_REGISTRATION__DECISION_CANCEL); + model.param(CLIENT_REG_FORM__HIDDEN_FIELDS_SECTION_TAG, HiddenFormFields.newForm() // + .add(CLIENT_REGISTRATION__APPLICATION_GUID, data.getClientGuid()) // + .add(OAuthConstants.SESSION_AUTHENTICITY_TOKEN, data.getAuthenticityToken())// + .build()); + return model; + } +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/writers/ClientRegistrationResponseHtmlWriter.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/writers/ClientRegistrationResponseHtmlWriter.java new file mode 100644 index 00000000000..c0bb030cb1c --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/internal/security/oauth2/provider/writers/ClientRegistrationResponseHtmlWriter.java @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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.internal.security.oauth2.provider.writers; + +import static org.eclipse.osee.jaxrs.server.internal.JaxRsUtils.asTemplateValue; +import javax.ws.rs.ext.Provider; +import org.eclipse.osee.framework.jdk.core.type.ViewModel; +import org.eclipse.osee.jaxrs.server.internal.resources.AbstractHtmlWriter; +import org.eclipse.osee.jaxrs.server.internal.security.oauth2.provider.endpoints.ClientRegistrationResponse; + +/** + * @author Roberto E. Escobar + */ +@Provider +public class ClientRegistrationResponseHtmlWriter extends AbstractHtmlWriter<ClientRegistrationResponse> { + + //@formatter:off + private static final String CLIENT_REG_CONFIRM_PAGE__TEMPLATE = "client_registration.html"; + private static final String CLIENT_REG_CONFIRM_PAGE__RESOURCE_SERVER_NAME_TAG = "resourceServerName"; + private static final String CLIENT_REG_CONFIRM_PAGE__CLIENT_ID_TAG = "clientId"; + private static final String CLIENT_REG_CONFIRM_PAGE__CLIENT_SECRET_TAG = "clientSecret"; + //@formatter:on + + @Override + public Class<ClientRegistrationResponse> getSupportedClass() { + return ClientRegistrationResponse.class; + } + + @Override + public ViewModel asViewModel(ClientRegistrationResponse data) { + ViewModel model = new ViewModel(CLIENT_REG_CONFIRM_PAGE__TEMPLATE); + model.param(CLIENT_REG_CONFIRM_PAGE__RESOURCE_SERVER_NAME_TAG, asTemplateValue(data.getResourceServerName())); + model.param(CLIENT_REG_CONFIRM_PAGE__CLIENT_ID_TAG, asTemplateValue(data.getClientId())); + model.param(CLIENT_REG_CONFIRM_PAGE__CLIENT_SECRET_TAG, asTemplateValue(data.getClientSecret())); + return model; + } + +} diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsOAuthStorage.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsOAuthStorage.java index b51e2df9f53..0fceae66c35 100644 --- a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsOAuthStorage.java +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/JaxRsOAuthStorage.java @@ -10,11 +10,23 @@ *******************************************************************************/ package org.eclipse.osee.jaxrs.server.security; +import org.eclipse.osee.framework.jdk.core.type.OseePrincipal; + /** * @author Roberto E. Escobar */ public interface JaxRsOAuthStorage { + long getClientUuidByKey(String clientKey); + + OAuthClient getClientByClientGuid(String guid); + + OAuthClient getClientByClientKey(String clientKey); + + void storeClient(OseePrincipal principal, OAuthClient client); + + void removeClient(OseePrincipal principal, OAuthClient client); + OAuthCodeGrant getCodeGrant(String code); void storeCodeGrant(OAuthCodeGrant codeGrant); 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 b51a1f7ff08..43af6a4fd90 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,6 +10,7 @@ *******************************************************************************/ package org.eclipse.osee.jaxrs.server.security; +import org.eclipse.osee.jaxrs.server.security.JaxRsAuthenticator.Subject; /** * @author Roberto E. Escobar @@ -22,4 +23,6 @@ public interface JaxRsSessionProvider { String getSessionToken(Long subjectId); + Subject getSubjectById(Long subjectId); + }
\ No newline at end of file diff --git a/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/OAuthClient.java b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/OAuthClient.java new file mode 100644 index 00000000000..1d7c67cd341 --- /dev/null +++ b/plugins/org.eclipse.osee.jaxrs.server/src/org/eclipse/osee/jaxrs/server/security/OAuthClient.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * 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.security; + +import java.io.InputStream; +import java.util.List; +import java.util.Map; +import org.eclipse.osee.framework.jdk.core.type.Identity; +import com.google.common.io.InputSupplier; + +/** + * @author Roberto E. Escobar + */ +public interface OAuthClient extends Identity<String> { + + long getClientUuid(); + + long getSubjectId(); + + String getClientId(); + + String getClientSecret(); + + List<String> getApplicationCertificates(); + + String getApplicationDescription(); + + String getApplicationLogoUri(); + + String getApplicationName(); + + String getApplicationWebUri(); + + Map<String, String> getProperties(); + + List<String> getRedirectUris(); + + List<String> getAllowedGrantTypes(); + + List<String> getRegisteredAudiences(); + + List<String> getRegisteredScopes(); + + boolean isConfidential(); + + boolean hasApplicationLogoSupplier(); + + InputSupplier<InputStream> getApplicationLogoSupplier(); + +} |