Search in sources :

Example 21 with AccountException

use of com.google.gerrit.server.account.AccountException in project gerrit by GerritCodeReview.

the class ConfirmEmail method apply.

@Override
public Response<?> apply(ConfigResource rsrc, Input input) throws AuthException, UnprocessableEntityException, AccountException, OrmException, IOException, ConfigInvalidException {
    CurrentUser user = self.get();
    if (!user.isIdentifiedUser()) {
        throw new AuthException("Authentication required");
    }
    if (input == null) {
        input = new Input();
    }
    if (input.token == null) {
        throw new UnprocessableEntityException("missing token");
    }
    try {
        EmailTokenVerifier.ParsedToken token = emailTokenVerifier.decode(input.token);
        Account.Id accId = user.getAccountId();
        if (accId.equals(token.getAccountId())) {
            accountManager.link(accId, token.toAuthRequest());
            return Response.none();
        }
        throw new UnprocessableEntityException("invalid token");
    } catch (EmailTokenVerifier.InvalidTokenException e) {
        throw new UnprocessableEntityException("invalid token");
    } catch (AccountException e) {
        throw new UnprocessableEntityException(e.getMessage());
    }
}
Also used : UnprocessableEntityException(com.google.gerrit.extensions.restapi.UnprocessableEntityException) Account(com.google.gerrit.reviewdb.client.Account) DefaultInput(com.google.gerrit.extensions.restapi.DefaultInput) Input(com.google.gerrit.server.config.ConfirmEmail.Input) EmailTokenVerifier(com.google.gerrit.server.mail.EmailTokenVerifier) CurrentUser(com.google.gerrit.server.CurrentUser) AccountException(com.google.gerrit.server.account.AccountException) AuthException(com.google.gerrit.extensions.restapi.AuthException)

Example 22 with AccountException

use of com.google.gerrit.server.account.AccountException in project gerrit by GerritCodeReview.

the class Helper method queryForGroups.

Set<AccountGroup.UUID> queryForGroups(final DirContext ctx, String username, LdapQuery.Result account) throws NamingException {
    final LdapSchema schema = getSchema(ctx);
    final Set<String> groupDNs = new HashSet<>();
    if (!schema.groupMemberQueryList.isEmpty()) {
        final HashMap<String, String> params = new HashMap<>();
        if (account == null) {
            try {
                account = findAccount(schema, ctx, username, false);
            } catch (AccountException e) {
                return Collections.emptySet();
            }
        }
        for (String name : schema.groupMemberQueryList.get(0).getParameters()) {
            params.put(name, account.get(name));
        }
        params.put(LdapRealm.USERNAME, username);
        for (LdapQuery groupMemberQuery : schema.groupMemberQueryList) {
            for (LdapQuery.Result r : groupMemberQuery.query(ctx, params, groupSearchLatencyTimer)) {
                try (Timer0.Context ignored = groupExpansionLatencyTimer.start()) {
                    recursivelyExpandGroups(groupDNs, schema, ctx, r.getDN());
                }
            }
        }
    }
    if (schema.accountMemberField != null) {
        if (account == null || account.getAll(schema.accountMemberField) == null) {
            try {
                account = findAccount(schema, ctx, username, true);
            } catch (AccountException e) {
                return Collections.emptySet();
            }
        }
        final Attribute groupAtt = account.getAll(schema.accountMemberField);
        if (groupAtt != null) {
            final NamingEnumeration<?> groups = groupAtt.getAll();
            try {
                while (groups.hasMore()) {
                    final String nextDN = (String) groups.next();
                    recursivelyExpandGroups(groupDNs, schema, ctx, nextDN);
                }
            } catch (PartialResultException e) {
            // Ignored
            }
        }
    }
    final Set<AccountGroup.UUID> actual = new HashSet<>();
    for (String dn : groupDNs) {
        actual.add(AccountGroup.uuid(LDAP_UUID + dn));
    }
    if (actual.isEmpty()) {
        return Collections.emptySet();
    }
    return ImmutableSet.copyOf(actual);
}
Also used : HashMap(java.util.HashMap) Attribute(javax.naming.directory.Attribute) PartialResultException(javax.naming.PartialResultException) ParameterizedString(com.google.gerrit.common.data.ParameterizedString) AccountException(com.google.gerrit.server.account.AccountException) Timer0(com.google.gerrit.metrics.Timer0) HashSet(java.util.HashSet)

Example 23 with AccountException

use of com.google.gerrit.server.account.AccountException in project gerrit by GerritCodeReview.

the class OAuthRealm method authenticate.

/**
 * Authenticates with the {@link OAuthLoginProvider} specified in the authentication request.
 *
 * <p>{@link AccountManager} calls this method without password if authenticity of the user has
 * already been established. In that case we can skip the authentication request to the {@code
 * OAuthLoginService}.
 *
 * @param who the authentication request.
 * @return the authentication request with resolved email address and display name in case the
 *     authenticity of the user could be established; otherwise {@code who} is returned unchanged.
 * @throws AccountException if the authentication request with the OAuth2 server failed or no
 *     {@code OAuthLoginProvider} was available to handle the request.
 */
@Override
public AuthRequest authenticate(AuthRequest who) throws AccountException {
    if (Strings.isNullOrEmpty(who.getPassword())) {
        return who;
    }
    if (Strings.isNullOrEmpty(who.getAuthPlugin()) || Strings.isNullOrEmpty(who.getAuthProvider())) {
        throw new AccountException("Cannot authenticate");
    }
    OAuthLoginProvider loginProvider = loginProviders.get(who.getAuthPlugin(), who.getAuthProvider());
    if (loginProvider == null) {
        throw new AccountException("Cannot authenticate");
    }
    OAuthUserInfo userInfo;
    try {
        userInfo = loginProvider.login(who.getUserName().orElse(null), who.getPassword());
    } catch (IOException e) {
        throw new AccountException("Cannot authenticate", e);
    }
    if (userInfo == null) {
        throw new AccountException("Cannot authenticate");
    }
    if (!Strings.isNullOrEmpty(userInfo.getEmailAddress()) && (!who.getUserName().isPresent() || !allowsEdit(AccountFieldName.REGISTER_NEW_EMAIL))) {
        who.setEmailAddress(userInfo.getEmailAddress());
    }
    if (!Strings.isNullOrEmpty(userInfo.getDisplayName()) && (Strings.isNullOrEmpty(who.getDisplayName()) || !allowsEdit(AccountFieldName.FULL_NAME))) {
        who.setDisplayName(userInfo.getDisplayName());
    }
    return who;
}
Also used : AccountException(com.google.gerrit.server.account.AccountException) OAuthUserInfo(com.google.gerrit.extensions.auth.oauth.OAuthUserInfo) IOException(java.io.IOException) OAuthLoginProvider(com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider)

Example 24 with AccountException

use of com.google.gerrit.server.account.AccountException in project gerrit by GerritCodeReview.

the class LdapAuthBackend method authenticate.

@Override
public AuthUser authenticate(AuthRequest req) throws MissingCredentialsException, InvalidCredentialsException, UnknownUserException, UserNotAllowedException, AuthException {
    if (!req.getUsername().isPresent() || !req.getPassword().isPresent()) {
        throw new MissingCredentialsException();
    }
    String username = lowerCaseUsername ? req.getUsername().map(u -> u.toLowerCase(Locale.US)).get() : req.getUsername().get();
    try {
        final DirContext ctx;
        if (authConfig.getAuthType() == AuthType.LDAP_BIND) {
            ctx = helper.authenticate(username, req.getPassword().get());
        } else {
            ctx = helper.open();
        }
        try {
            final Helper.LdapSchema schema = helper.getSchema(ctx);
            final LdapQuery.Result m = helper.findAccount(schema, ctx, username, false);
            if (authConfig.getAuthType() == AuthType.LDAP) {
                // We found the user account, but we need to verify
                // the password matches it before we can continue.
                // 
                helper.close(helper.authenticate(m.getDN(), req.getPassword().get()));
            }
            return new AuthUser(AuthUser.UUID.create(username), username);
        } finally {
            helper.close(ctx);
        }
    } catch (AccountException e) {
        logger.atSevere().withCause(e).log("Cannot query LDAP to authenticate user");
        throw new InvalidCredentialsException("Cannot query LDAP for account", e);
    } catch (IOException | NamingException e) {
        logger.atSevere().withCause(e).log("Cannot query LDAP to authenticate user");
        throw new AuthException("Cannot query LDAP for account", e);
    } catch (LoginException e) {
        logger.atSevere().withCause(e).log("Cannot authenticate server via JAAS");
        throw new AuthException("Cannot query LDAP for account", e);
    }
}
Also used : AuthException(com.google.gerrit.server.auth.AuthException) AuthUser(com.google.gerrit.server.auth.AuthUser) DirContext(javax.naming.directory.DirContext) IOException(java.io.IOException) AccountException(com.google.gerrit.server.account.AccountException) InvalidCredentialsException(com.google.gerrit.server.auth.InvalidCredentialsException) LoginException(javax.security.auth.login.LoginException) MissingCredentialsException(com.google.gerrit.server.auth.MissingCredentialsException) NamingException(javax.naming.NamingException)

Example 25 with AccountException

use of com.google.gerrit.server.account.AccountException in project gerrit by GerritCodeReview.

the class OpenIdServiceImpl method doAuth.

/**
 * Called by {@link OpenIdLoginServlet} doGet, doPost
 */
void doAuth(HttpServletRequest req, HttpServletResponse rsp) throws Exception {
    if (OMODE_CANCEL.equals(req.getParameter(OPENID_MODE))) {
        cancel(req, rsp);
        return;
    }
    // Process the authentication response.
    // 
    final SignInMode mode = signInMode(req);
    final String openidIdentifier = req.getParameter("openid.identity");
    final String claimedIdentifier = req.getParameter(P_CLAIMED);
    final String returnToken = req.getParameter(P_TOKEN);
    final boolean remember = "1".equals(req.getParameter(P_REMEMBER));
    final String rediscoverIdentifier = claimedIdentifier != null ? claimedIdentifier : openidIdentifier;
    final State state;
    if (!isAllowedOpenID(rediscoverIdentifier) || !isAllowedOpenID(openidIdentifier) || (claimedIdentifier != null && !isAllowedOpenID(claimedIdentifier))) {
        cancelWithError(req, rsp, "Provider not allowed");
        return;
    }
    state = init(req, rediscoverIdentifier, mode, remember, returnToken);
    if (state == null) {
        // Re-discovery must have failed, we can't run a login.
        // 
        cancel(req, rsp);
        return;
    }
    final String returnTo = req.getParameter("openid.return_to");
    if (returnTo != null && returnTo.contains("openid.rpnonce=")) {
        // Some providers (claimid.com) seem to embed these request
        // parameters into our return_to URL, and then give us them
        // in the return_to request parameter. But not all.
        // 
        state.retTo.put("openid.rpnonce", req.getParameter("openid.rpnonce"));
        state.retTo.put("openid.rpsig", req.getParameter("openid.rpsig"));
    }
    final VerificationResult result = manager.verify(state.retTo.toString(), new ParameterList(req.getParameterMap()), state.discovered);
    if (result.getVerifiedId() == null) /* authentication failure */
    {
        if ("Nonce verification failed.".equals(result.getStatusMsg())) {
            // We might be suffering from clock skew on this system.
            // 
            logger.atSevere().log("OpenID failure: %s  Likely caused by clock skew on this server," + " install/configure NTP.", result.getStatusMsg());
            cancelWithError(req, rsp, result.getStatusMsg());
        } else if (result.getStatusMsg() != null) {
            // Authentication failed.
            // 
            logger.atSevere().log("OpenID failure: %s", result.getStatusMsg());
            cancelWithError(req, rsp, result.getStatusMsg());
        } else {
            // Assume authentication was canceled.
            // 
            cancel(req, rsp);
        }
        return;
    }
    final Message authRsp = result.getAuthResponse();
    SRegResponse sregRsp = null;
    FetchResponse fetchRsp = null;
    if (0 <= papeMaxAuthAge) {
        PapeResponse ext;
        boolean unsupported = false;
        try {
            ext = (PapeResponse) authRsp.getExtension(PapeMessage.OPENID_NS_PAPE);
        } catch (MessageException err) {
            // Far too many providers are unable to provide PAPE extensions
            // right now. Instead of blocking all of them log the error and
            // let the authentication complete anyway.
            // 
            logger.atSevere().withCause(err).log("Invalid PAPE response from %s", openidIdentifier);
            unsupported = true;
            ext = null;
        }
        if (!unsupported && ext == null) {
            logger.atSevere().log("No PAPE extension response from %s", openidIdentifier);
            cancelWithError(req, rsp, "OpenID provider does not support PAPE.");
            return;
        }
    }
    if (authRsp.hasExtension(SRegMessage.OPENID_NS_SREG)) {
        final MessageExtension ext = authRsp.getExtension(SRegMessage.OPENID_NS_SREG);
        if (ext instanceof SRegResponse) {
            sregRsp = (SRegResponse) ext;
        }
    }
    if (authRsp.hasExtension(AxMessage.OPENID_NS_AX)) {
        final MessageExtension ext = authRsp.getExtension(AxMessage.OPENID_NS_AX);
        if (ext instanceof FetchResponse) {
            fetchRsp = (FetchResponse) ext;
        }
    }
    final com.google.gerrit.server.account.AuthRequest areq = authRequestFactory.create(externalIdKeyFactory.parse(openidIdentifier));
    if (sregRsp != null) {
        areq.setDisplayName(sregRsp.getAttributeValue("fullname"));
        areq.setEmailAddress(sregRsp.getAttributeValue("email"));
    } else if (fetchRsp != null) {
        final String firstName = fetchRsp.getAttributeValue("FirstName");
        final String lastName = fetchRsp.getAttributeValue("LastName");
        final StringBuilder n = new StringBuilder();
        if (firstName != null && firstName.length() > 0) {
            n.append(firstName);
        }
        if (lastName != null && lastName.length() > 0) {
            if (n.length() > 0) {
                n.append(' ');
            }
            n.append(lastName);
        }
        areq.setDisplayName(n.length() > 0 ? n.toString() : null);
        areq.setEmailAddress(fetchRsp.getAttributeValue("Email"));
    }
    if (openIdDomains != null && !openIdDomains.isEmpty()) {
        // Administrator limited email domains, which can be used for OpenID.
        // Login process will only work if the passed email matches one
        // of these domains.
        // 
        final String email = areq.getEmailAddress();
        int emailAtIndex = email.lastIndexOf('@');
        if (emailAtIndex >= 0 && emailAtIndex < email.length() - 1) {
            final String emailDomain = email.substring(emailAtIndex);
            boolean match = false;
            for (String domain : openIdDomains) {
                if (emailDomain.equalsIgnoreCase(domain)) {
                    match = true;
                    break;
                }
            }
            if (!match) {
                logger.atSevere().log("Domain disallowed: %s", emailDomain);
                cancelWithError(req, rsp, "Domain disallowed");
                return;
            }
        }
    }
    if (claimedIdentifier != null) {
        // The user used a claimed identity which has delegated to the verified
        // identity we have in our AuthRequest above. We still should have a
        // link between the two, so set one up if not present.
        // 
        Optional<Account.Id> claimedId = accountManager.lookup(claimedIdentifier);
        Optional<Account.Id> actualId = accountManager.lookup(areq.getExternalIdKey().get());
        if (claimedId.isPresent() && actualId.isPresent()) {
            if (claimedId.get().equals(actualId.get())) {
            // Both link to the same account, that's what we expected.
            } else {
                // This is (for now) a fatal error. There are two records
                // for what might be the same user.
                // 
                logger.atSevere().log("OpenID accounts disagree over user identity:\n" + "  Claimed ID: %s is %s\n" + "  Delgate ID: %s is %s", claimedId.get(), claimedIdentifier, actualId.get(), areq.getExternalIdKey());
                cancelWithError(req, rsp, "Contact site administrator");
                return;
            }
        } else if (!claimedId.isPresent() && actualId.isPresent()) {
            // Older account, the actual was already created but the claimed
            // was missing due to a bug in Gerrit. Link the claimed.
            // 
            final com.google.gerrit.server.account.AuthRequest linkReq = authRequestFactory.create(externalIdKeyFactory.parse(claimedIdentifier));
            linkReq.setDisplayName(areq.getDisplayName());
            linkReq.setEmailAddress(areq.getEmailAddress());
            accountManager.link(actualId.get(), linkReq);
        } else if (claimedId.isPresent() && !actualId.isPresent()) {
            // Claimed account already exists, but it smells like the user has
            // changed their delegate to point to a different provider. Link
            // the new provider.
            // 
            accountManager.link(claimedId.get(), areq);
        } else {
        // Both are null, we are going to create a new account below.
        }
    }
    try {
        final com.google.gerrit.server.account.AuthResult arsp;
        switch(mode) {
            case REGISTER:
            case SIGN_IN:
                arsp = accountManager.authenticate(areq);
                final Cookie lastId = new Cookie(OpenIdUrls.LASTID_COOKIE, "");
                lastId.setPath(req.getContextPath() + "/login/");
                if (remember) {
                    lastId.setValue(rediscoverIdentifier);
                    lastId.setMaxAge(LASTID_AGE);
                } else {
                    lastId.setMaxAge(0);
                }
                rsp.addCookie(lastId);
                webSession.get().login(arsp, remember);
                if (arsp.isNew() && claimedIdentifier != null) {
                    final com.google.gerrit.server.account.AuthRequest linkReq = authRequestFactory.create(externalIdKeyFactory.parse(claimedIdentifier));
                    linkReq.setDisplayName(areq.getDisplayName());
                    linkReq.setEmailAddress(areq.getEmailAddress());
                    accountManager.link(arsp.getAccountId(), linkReq);
                }
                callback(arsp.isNew(), req, rsp);
                break;
            case LINK_IDENTIY:
                {
                    arsp = accountManager.link(identifiedUser.get().getAccountId(), areq);
                    webSession.get().login(arsp, remember);
                    callback(false, req, rsp);
                    break;
                }
        }
    } catch (AccountException e) {
        logger.atSevere().withCause(e).log("OpenID authentication failure");
        cancelWithError(req, rsp, "Contact site administrator");
    }
}
Also used : AuthRequest(org.openid4java.message.AuthRequest) SRegMessage(org.openid4java.message.sreg.SRegMessage) PapeMessage(org.openid4java.message.pape.PapeMessage) AxMessage(org.openid4java.message.ax.AxMessage) Message(org.openid4java.message.Message) SRegResponse(org.openid4java.message.sreg.SRegResponse) MessageException(org.openid4java.message.MessageException) Cookie(javax.servlet.http.Cookie) FetchResponse(org.openid4java.message.ax.FetchResponse) MessageExtension(org.openid4java.message.MessageExtension) VerificationResult(org.openid4java.consumer.VerificationResult) AccountException(com.google.gerrit.server.account.AccountException) ParameterList(org.openid4java.message.ParameterList) PapeResponse(org.openid4java.message.pape.PapeResponse)

Aggregations

AccountException (com.google.gerrit.server.account.AccountException)36 AuthRequest (com.google.gerrit.server.account.AuthRequest)19 Account (com.google.gerrit.entities.Account)12 ExternalId (com.google.gerrit.server.account.externalids.ExternalId)11 Test (org.junit.Test)10 AbstractDaemonTest (com.google.gerrit.acceptance.AbstractDaemonTest)9 AuthResult (com.google.gerrit.server.account.AuthResult)7 ParameterizedString (com.google.gerrit.common.data.ParameterizedString)6 AccountState (com.google.gerrit.server.account.AccountState)5 IOException (java.io.IOException)5 AuthException (com.google.gerrit.extensions.restapi.AuthException)4 AuthenticationUnavailableException (com.google.gerrit.server.auth.AuthenticationUnavailableException)4 HashMap (java.util.HashMap)4 ResourceConflictException (com.google.gerrit.extensions.restapi.ResourceConflictException)3 UnprocessableEntityException (com.google.gerrit.extensions.restapi.UnprocessableEntityException)3 CurrentUser (com.google.gerrit.server.CurrentUser)3 NamingException (javax.naming.NamingException)3 DirContext (javax.naming.directory.DirContext)3 LoginException (javax.security.auth.login.LoginException)3 OAuthLoginProvider (com.google.gerrit.extensions.auth.oauth.OAuthLoginProvider)2