From a43086e745253e97c610cb2c7df5d42e5f065b61 Mon Sep 17 00:00:00 2001 From: Kohsuke Kawaguchi Date: Wed, 5 Jan 2011 19:58:04 -0800 Subject: [PATCH] unclaimed identity should commence a signup sequence --- .../security/FederatedLoginService.java | 60 +++++++++++++++++-- .../FederatedLoginServiceUserProperty.java | 25 +++++++- .../java/hudson/security/SecurityRealm.java | 24 ++++++++ .../UnclaimedIdentityException/error.jelly | 36 +++++++++++ .../error.properties | 6 ++ 5 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.jelly create mode 100644 core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.properties diff --git a/core/src/main/java/hudson/security/FederatedLoginService.java b/core/src/main/java/hudson/security/FederatedLoginService.java index 865236ec9d..897a56ec49 100644 --- a/core/src/main/java/hudson/security/FederatedLoginService.java +++ b/core/src/main/java/hudson/security/FederatedLoginService.java @@ -1,3 +1,26 @@ +/* + * The MIT License + * + * Copyright (c) 2010, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package hudson.security; import hudson.ExtensionList; @@ -8,7 +31,11 @@ import hudson.model.UserProperty; import org.acegisecurity.context.SecurityContextHolder; import org.acegisecurity.providers.UsernamePasswordAuthenticationToken; import org.acegisecurity.userdetails.UserDetails; +import org.kohsuke.stapler.HttpResponse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import javax.servlet.ServletException; import java.io.IOException; /** @@ -61,7 +88,7 @@ import java.io.IOException; * "/federatedLoginService/openid" as the URL. * * @author Kohsuke Kawaguchi - * @since 1.393 + * @since 1.394 */ public abstract class FederatedLoginService implements ExtensionPoint { /** @@ -113,6 +140,12 @@ public abstract class FederatedLoginService implements ExtensionPoint { */ public abstract String getEmailAddress(); + /** + * Returns a human-readable pronoun that describes this kind of identifier. + * This is used for rendering UI. For example, "OpenID", "Twitter ID", etc. + */ + public abstract String getPronoun(); + /** * Locates the user who owns this identifier. */ @@ -136,7 +169,9 @@ public abstract class FederatedLoginService implements ExtensionPoint { * the current session. IOW, it signs in the user. * * @throws UnclaimedIdentityException - * If this identifier is not claimed by anyone. + * If this identifier is not claimed by anyone. If you just let this exception propagate + * to the caller of your "doXyz" method, it will either render an error page or initiate + * a user registration session (provided that {@link SecurityRealm} supports that.) */ public final void signin() throws UnclaimedIdentityException { User u = locateUser(); @@ -148,7 +183,7 @@ public abstract class FederatedLoginService implements ExtensionPoint { token.setDetails(d); SecurityContextHolder.getContext().setAuthentication(token); } else { - // unassociated identity + // Unassociated identity. throw new UnclaimedIdentityException(this); } } @@ -179,11 +214,28 @@ public abstract class FederatedLoginService implements ExtensionPoint { } } - public static class UnclaimedIdentityException extends Exception { + public static class UnclaimedIdentityException extends Exception implements HttpResponse { public final FederatedIdentity identity; + public UnclaimedIdentityException(FederatedIdentity identity) { this.identity = identity; } + + public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException { + SecurityRealm sr = Hudson.getInstance().getSecurityRealm(); + if (sr.allowsSignup()) { + try { + sr.commenceSignup(identity).generateResponse(req,rsp,node); + return; + } catch (UnsupportedOperationException e) { + // fall through + } + } + + // this security realm doesn't support user registration. + // just report an error + req.getView(this,"error").forward(req,rsp); + } } public static ExtensionList all() { diff --git a/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java b/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java index 3784f4d7dd..ff2fcb63ad 100644 --- a/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java +++ b/core/src/main/java/hudson/security/FederatedLoginServiceUserProperty.java @@ -1,3 +1,26 @@ +/* + * The MIT License + * + * Copyright (c) 2010, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ package hudson.security; import hudson.model.UserProperty; @@ -11,7 +34,7 @@ import java.util.Set; /** * * @author Kohsuke Kawaguchi - * @since 1.393 + * @since 1.394 * @see FederatedLoginService */ public class FederatedLoginServiceUserProperty extends UserProperty { diff --git a/core/src/main/java/hudson/security/SecurityRealm.java b/core/src/main/java/hudson/security/SecurityRealm.java index 8818cc729b..95f0eb04e8 100644 --- a/core/src/main/java/hudson/security/SecurityRealm.java +++ b/core/src/main/java/hudson/security/SecurityRealm.java @@ -33,6 +33,7 @@ import hudson.cli.CLICommand; import hudson.model.AbstractDescribableImpl; import hudson.model.Descriptor; import hudson.model.Hudson; +import hudson.security.FederatedLoginService.FederatedIdentity; import hudson.util.DescriptorList; import hudson.util.PluginServletFilter; import hudson.util.spring.BeanBuilder; @@ -47,6 +48,7 @@ import static org.acegisecurity.ui.rememberme.TokenBasedRememberMeServices.ACEGI import org.acegisecurity.userdetails.UserDetailsService; import org.acegisecurity.userdetails.UserDetails; import org.acegisecurity.userdetails.UsernameNotFoundException; +import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; @@ -299,6 +301,28 @@ public abstract class SecurityRealm extends AbstractDescribableImpl + * If the user logs in through a {@link FederatedLoginService}, verified that the current user + * owns an {@linkplain FederatedIdentity identity}, but no existing user account has claimed that identity, + * then this method is invoked. + * + *

+ * The expected behaviour is to confirm that the user would like to create a new account, and + * associate this federated identity to the newly created account (via {@link FederatedIdentity#addToCurrentUser()}. + * + * @throws UnsupportedOperationException + * If this implementation doesn't support the signup through this mechanism. + * This is the default implementation. + * + * @since 1.394 + */ + public HttpResponse commenceSignup(FederatedIdentity identity) { + throw new UnsupportedOperationException(); + } + /** * {@link DefaultManageableImageCaptchaService} holder to defer initialization. */ diff --git a/core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.jelly b/core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.jelly new file mode 100644 index 0000000000..cc7b9451a5 --- /dev/null +++ b/core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.jelly @@ -0,0 +1,36 @@ + + + + + + + +

${%loginError(it.identifier.pronoun)}

+

${%blurb(it.identifier.pronoun, it.identifier.identifier)}

+ + + \ No newline at end of file diff --git a/core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.properties b/core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.properties new file mode 100644 index 0000000000..8b9110d472 --- /dev/null +++ b/core/src/main/resources/hudson/security/FederatedLoginService/UnclaimedIdentityException/error.properties @@ -0,0 +1,6 @@ +loginError=Login Error: unassociated {0} + +blurb={0} "{1}" is not associated with any of the Hudson user account. \ + Note that if you already have a user account and is trying to associate a {0} with your account, \ + this is a wrong place. To do so,
  1. Login
  2. Click on your name
  3. Click on the "Configure" link, and \ + then
  4. associate a new {0} from that page
-- GitLab