Search in sources :

Example 21 with AuthInfo

use of com.tremolosecurity.proxy.auth.AuthInfo in project OpenUnison by TremoloSecurity.

the class U2fAuth method doGet.

@Override
public void doGet(HttpServletRequest request, HttpServletResponse response, AuthStep as) throws IOException, ServletException {
    if (request.getParameter("signResponse") == null) {
        startAuthentication(request, response, as);
    } else {
        SignResponseHolder srh = gson.fromJson(request.getParameter("signResponse"), SignResponseHolder.class);
        AuthInfo userData = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
        // SharedSession.getSharedSession().getSession(req.getSession().getId());
        HttpSession session = ((HttpServletRequest) request).getSession();
        UrlHolder holder = (UrlHolder) request.getAttribute(ProxyConstants.AUTOIDM_CFG);
        RequestHolder reqHolder = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL)).getHolder();
        String urlChain = holder.getUrl().getAuthChain();
        AuthChainType act = holder.getConfig().getAuthChains().get(reqHolder.getAuthChainName());
        AuthMechType amt = act.getAuthMech().get(as.getId());
        HashMap<String, Attribute> authParams = (HashMap<String, Attribute>) session.getAttribute(ProxyConstants.AUTH_MECH_PARAMS);
        String challengeStoreAttribute = authParams.get("attribute").getValues().get(0);
        String encyrptionKeyName = authParams.get("encryptionKeyName").getValues().get(0);
        String uidAttributeName = authParams.get("uidAttributeName").getValues().get(0);
        String workflowName = authParams.get("workflowName").getValues().get(0);
        if (srh.getErrorCode() > 0) {
            logger.warn("Browser could not validate u2f token for user '" + userData.getUserDN() + "' : " + srh.getErrorCode());
            if (amt.getRequired().equals("required")) {
                as.setSuccess(false);
            }
            holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
            return;
        }
        U2FServer u2f = (U2FServer) request.getSession().getAttribute(SERVER);
        SignResponse sigResp = new SignResponse(srh.getKeyHandle(), srh.getSignatureData(), srh.getClientData(), srh.getSessionId());
        try {
            u2f.processSignResponse(sigResp);
        } catch (U2FException e) {
            logger.warn("Could not authenticate user : '" + e.getMessage() + "'");
            if (amt.getRequired().equals("required")) {
                as.setSuccess(false);
            }
            holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
            return;
        }
        String encrypted;
        try {
            encrypted = U2fUtil.encode(u2f.getAllSecurityKeys("doesntmatter"), encyrptionKeyName);
        } catch (Exception e) {
            throw new ServletException("Could not encrypt keys");
        }
        WFCall wc = new WFCall();
        wc.setName(workflowName);
        wc.setUidAttributeName(uidAttributeName);
        TremoloUser tu = new TremoloUser();
        tu.setUid(userData.getAttribs().get(uidAttributeName).getValues().get(0));
        tu.getAttributes().add(new Attribute(uidAttributeName, userData.getAttribs().get(uidAttributeName).getValues().get(0)));
        tu.getAttributes().add(new Attribute(challengeStoreAttribute, encrypted));
        wc.setUser(tu);
        Map<String, Object> req = new HashMap<String, Object>();
        req.put(ProvisioningParams.UNISON_EXEC_TYPE, ProvisioningParams.UNISON_EXEC_SYNC);
        wc.setRequestParams(req);
        try {
            GlobalEntries.getGlobalEntries().getConfigManager().getProvisioningEngine().getWorkFlow(workflowName).executeWorkflow(wc);
        } catch (ProvisioningException e) {
            throw new ServletException("Could not save keys", e);
        }
        as.setSuccess(true);
        holder.getConfig().getAuthManager().nextAuth(request, response, session, false);
    }
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) U2FServer(com.google.u2f.server.U2FServer) WFCall(com.tremolosecurity.provisioning.service.util.WFCall) Attribute(com.tremolosecurity.saml.Attribute) HashMap(java.util.HashMap) HttpSession(javax.servlet.http.HttpSession) AuthMechType(com.tremolosecurity.config.xml.AuthMechType) RequestHolder(com.tremolosecurity.proxy.auth.RequestHolder) AuthController(com.tremolosecurity.proxy.auth.AuthController) ServletException(javax.servlet.ServletException) U2FException(com.google.u2f.U2FException) MalformedURLException(java.net.MalformedURLException) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) IOException(java.io.IOException) HttpServletRequest(javax.servlet.http.HttpServletRequest) UrlHolder(com.tremolosecurity.config.util.UrlHolder) ServletException(javax.servlet.ServletException) SignResponse(com.google.u2f.server.messages.SignResponse) TremoloUser(com.tremolosecurity.provisioning.service.util.TremoloUser) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) U2FException(com.google.u2f.U2FException) AuthChainType(com.tremolosecurity.config.xml.AuthChainType)

Example 22 with AuthInfo

use of com.tremolosecurity.proxy.auth.AuthInfo in project OpenUnison by TremoloSecurity.

the class TokenData method doPost.

public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    if (request.getHeader("Accept") != null && request.getHeader("Accept").startsWith("application/json")) {
        request.setAttribute("com.tremolosecurity.unison.proxy.noRedirectOnError", "com.tremolosecurity.unison.proxy.noRedirectOnError");
    }
    try {
        String action = (String) request.getAttribute(IDP.ACTION_NAME);
        if (action.contentEquals("completefed")) {
            this.completeFederation(request, response);
        } else if (action.equalsIgnoreCase("token")) {
            String code = request.getParameter("code");
            String clientID = request.getParameter("client_id");
            String clientSecret = request.getParameter("client_secret");
            String redirectURI = request.getParameter("redirect_uri");
            String grantType = request.getParameter("grant_type");
            String refreshToken = request.getParameter("refresh_token");
            if (clientID == null) {
                // this means that the clientid is in the Authorization header
                String azHeader = request.getHeader("Authorization");
                azHeader = azHeader.substring(azHeader.indexOf(' ') + 1).trim();
                azHeader = new String(org.apache.commons.codec.binary.Base64.decodeBase64(azHeader));
                clientID = azHeader.substring(0, azHeader.indexOf(':'));
                clientSecret = azHeader.substring(azHeader.indexOf(':') + 1);
            }
            AuthController ac = (AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL);
            UrlHolder holder = (UrlHolder) request.getAttribute(ProxyConstants.AUTOIDM_CFG);
            holder.getApp().getCookieConfig().getTimeout();
            if (refreshToken != null) {
                try {
                    refreshToken(response, clientID, clientSecret, refreshToken, holder, request, ac.getAuthInfo());
                } catch (Exception e1) {
                    logger.warn("Could not refresh token", e1);
                    AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, ac.getAuthInfo(), "NONE");
                    response.sendError(401);
                }
            } else if (grantType.equalsIgnoreCase("urn:ietf:params:oauth:grant-type:token-exchange")) {
                StsRequest stsRequest = new StsRequest();
                stsRequest.setAudience(request.getParameter("audience"));
                stsRequest.setDelegation(request.getParameter("actor_token") != null);
                stsRequest.setImpersonation(!stsRequest.isDelegation());
                stsRequest.setSubjectToken(request.getParameter("subject_token"));
                stsRequest.setSubjectTokenType(request.getParameter("subject_token_type"));
                stsRequest.setActorToken(request.getParameter("actor_token"));
                stsRequest.setActorTokenType(request.getParameter("actor_token_type"));
                stsRequest.setImpersonation(stsRequest.getActorToken() == null);
                stsRequest.setDelegation(stsRequest.getActorToken() != null);
                OpenIDConnectTrust trust = this.trusts.get(clientID);
                if (trust == null) {
                    String errorMessage = new StringBuilder().append("Trust '").append(clientID).append("' not found").toString();
                    logger.warn(errorMessage);
                    throw new Exception(errorMessage);
                }
                if (!trust.isSts()) {
                    String errorMessage = new StringBuilder().append("Trust '").append(clientID).append("' not an sts").toString();
                    logger.warn(errorMessage);
                    response.sendError(401);
                    return;
                }
                if (stsRequest.isImpersonation()) {
                    stsImpersontion(request, response, clientID, ac, holder, stsRequest, trust);
                } else {
                    if (!trust.isStsDelegation()) {
                        logger.warn(new StringBuilder().append("clientid '").append(clientID).append("' does not support delegation"));
                        response.sendError(403);
                    }
                    // validate the actor
                    X509Certificate sigCert = GlobalEntries.getGlobalEntries().getConfigManager().getCertificate(this.getJwtSigningKeyName());
                    if (sigCert == null) {
                        logger.error(new StringBuilder().append("JWT Signing Certificate '").append(this.getJwtSigningKeyName()).append("' does not exist").toString());
                        response.sendError(500);
                        return;
                    }
                    StringBuffer issuer = new StringBuffer();
                    // issuer.append(cfg.getAuthIdPPath()).append(this.idpName);
                    issuer.append(holder.getApp().getUrls().getUrl().get(0).getUri());
                    String issuerUrl = ProxyTools.getInstance().getFqdnUrl(issuer.toString(), request);
                    HttpSession session = request.getSession();
                    AuthInfo authData = ((AuthController) session.getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
                    TokenData actorTokenData = this.validateToken(stsRequest.getActorToken(), "actor_token", sigCert.getPublicKey(), issuerUrl, clientID, holder, request, authData, response, false);
                    if (actorTokenData == null) {
                        return;
                    }
                    String uidAttribute = this.getUidAttributeFromMap();
                    if (uidAttribute == null) {
                        logger.error(new StringBuilder().append("IdP ").append(holder.getApp().getName()).append(" does not have a sub attribute mapped to a user attribute").toString());
                        response.sendError(500);
                        return;
                    }
                    String authChainName = null;
                    AuthChainType actorAuthChain = null;
                    if (actorTokenData.amr != null) {
                        authChainName = this.getAmrToAuthChain().get(actorTokenData.amr);
                        if (authChainName != null) {
                            actorAuthChain = GlobalEntries.getGlobalEntries().getConfigManager().getAuthChains().get(authChainName);
                        }
                    }
                    AuthInfo actorAuth = this.jwtToAuthInfo(actorTokenData, uidAttribute, actorAuthChain, authChainName);
                    if (actorAuth == null) {
                        // don't think this can happen
                        logger.error("Could not create user auth object from jwt");
                        response.sendError(500);
                        return;
                    }
                    AzSys azSys = new AzSys();
                    if (!azSys.checkRules(actorAuth, GlobalEntries.getGlobalEntries().getConfigManager(), trust.getClientAzRules(), new HashMap<String, Object>())) {
                        AccessLog.log(AccessEvent.AzFail, holder.getApp(), request, actorAuth, new StringBuilder().append("client not authorized to exchange token for subject '").append(actorTokenData.subjectUid).append("'").toString());
                        response.sendError(403);
                        return;
                    }
                    if (!trust.getAllowedAudiences().contains(stsRequest.getAudience())) {
                        AccessLog.log(AccessEvent.AzFail, holder.getApp(), request, actorAuth, new StringBuilder().append("Audience '").append(stsRequest.getAudience()).append("' is not an authorized audience for sts '").append(trust.getTrustName()).append("'").toString());
                        response.sendError(403);
                        return;
                    }
                    OpenIDConnectTrust targetTrust = this.getTrusts().get(stsRequest.getAudience());
                    if (targetTrust == null) {
                        logger.warn(new StringBuilder().append("Audience '").append(stsRequest.getAudience()).append("' does not exist").toString());
                        response.sendError(404);
                        return;
                    }
                    TokenData subjectTokenData = this.validateToken(stsRequest.getSubjectToken(), "subject_token", sigCert.getPublicKey(), issuerUrl, null, holder, request, authData, response, true);
                    if (subjectTokenData == null) {
                        return;
                    }
                    authChainName = null;
                    actorAuthChain = null;
                    if (subjectTokenData.amr != null) {
                        authChainName = this.getAmrToAuthChain().get(subjectTokenData.amr);
                        if (authChainName != null) {
                            actorAuthChain = GlobalEntries.getGlobalEntries().getConfigManager().getAuthChains().get(authChainName);
                        }
                    }
                    AuthInfo subjectAuth = this.jwtToAuthInfo(subjectTokenData, uidAttribute, actorAuthChain, authChainName);
                    if (subjectAuth == null) {
                        // don't think this can happen
                        logger.error("Could not create user auth object from jwt");
                        response.sendError(500);
                        return;
                    }
                    if (!azSys.checkRules(subjectAuth, GlobalEntries.getGlobalEntries().getConfigManager(), trust.getSubjectAzRules(), new HashMap<String, Object>())) {
                        AccessLog.log(AccessEvent.AzFail, holder.getApp(), request, actorAuth, new StringBuilder().append("client not authorized to exchange token for subject '").append(subjectTokenData.subjectUid).append("'").toString());
                        response.sendError(403);
                        return;
                    }
                    OpenIDConnectAccessToken access = new OpenIDConnectAccessToken();
                    OidcSessionState oidcSession = this.createUserSession(request, stsRequest.getAudience(), holder, targetTrust, subjectAuth.getUserDN(), GlobalEntries.getGlobalEntries().getConfigManager(), access, UUID.randomUUID().toString(), subjectAuth.getAuthChain(), subjectTokenData.root, actorTokenData.root);
                    AccessLog.log(AccessEvent.AzSuccess, holder.getApp(), request, actorAuth, new StringBuilder().append("client '").append(trust.getTrustName()).append("' delegated to by '").append(subjectTokenData.subjectUid).append("', jti : '").append(access.getIdTokenId()).append("'").toString());
                    String idtoken = access.getId_token();
                    access.setRefresh_token(oidcSession.getRefreshToken());
                    Gson gson = new Gson();
                    String json = gson.toJson(access);
                    response.setContentType("application/json");
                    response.getOutputStream().write(json.getBytes("UTF-8"));
                    response.getOutputStream().flush();
                    if (logger.isDebugEnabled()) {
                        logger.debug("Token JSON : '" + json + "'");
                    }
                }
            } else if (grantType.equalsIgnoreCase("client_credentials")) {
                clientCredentialsGrant(request, response, clientID, clientSecret, ac, holder);
            } else {
                completeUserLogin(request, response, code, clientID, clientSecret, holder, ac.getAuthInfo());
            }
        }
    } catch (Throwable t) {
        if (request.getHeader("Accept") != null && request.getHeader("Accept").startsWith("application/json")) {
            response.sendError(500);
            response.setContentType("application/json");
            response.getWriter().print("{\"error\":\"invalid_request\"}");
            logger.error("Sending JSON Error", t);
        } else {
            if (t instanceof ServletException) {
                throw (ServletException) t;
            } else if (t instanceof IOException) {
                throw (IOException) t;
            } else {
                throw new ServletException("Error processing post", t);
            }
        }
    }
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) HashMap(java.util.HashMap) HttpSession(javax.servlet.http.HttpSession) Gson(com.google.gson.Gson) IOException(java.io.IOException) AuthController(com.tremolosecurity.proxy.auth.AuthController) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) LDAPException(com.novell.ldap.LDAPException) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) IOException(java.io.IOException) ServletException(javax.servlet.ServletException) URISyntaxException(java.net.URISyntaxException) InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) JoseException(org.jose4j.lang.JoseException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ParseException(org.json.simple.parser.ParseException) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) MalformedURLException(java.net.MalformedURLException) BadPaddingException(javax.crypto.BadPaddingException) X509Certificate(java.security.cert.X509Certificate) UrlHolder(com.tremolosecurity.config.util.UrlHolder) ServletException(javax.servlet.ServletException) AzSys(com.tremolosecurity.proxy.auth.AzSys) StsRequest(com.tremolosecurity.idp.providers.oidc.db.StsRequest) AuthChainType(com.tremolosecurity.config.xml.AuthChainType) OidcSessionState(com.tremolosecurity.idp.providers.oidc.model.OidcSessionState)

Example 23 with AuthInfo

use of com.tremolosecurity.proxy.auth.AuthInfo in project OpenUnison by TremoloSecurity.

the class TokenData method doGet.

public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    if (request.getHeader("Accept") != null && request.getHeader("Accept").startsWith("application/json")) {
        request.setAttribute("com.tremolosecurity.unison.proxy.noRedirectOnError", "com.tremolosecurity.unison.proxy.noRedirectOnError");
    }
    String action = (String) request.getAttribute(IDP.ACTION_NAME);
    UrlHolder holder = (UrlHolder) request.getAttribute(ProxyConstants.AUTOIDM_CFG);
    if (holder == null) {
        throw new ServletException("Holder is null");
    }
    AuthController ac = ((AuthController) request.getSession().getAttribute(ProxyConstants.AUTH_CTL));
    if (action.equalsIgnoreCase(".well-known/openid-configuration")) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        String json = gson.toJson(new OpenIDConnectConfig(this.authURI, request, mapper));
        response.setContentType("application/json");
        response.getWriter().print(json);
        AccessLog.log(AccessEvent.AzSuccess, holder.getApp(), (HttpServletRequest) request, ac.getAuthInfo(), "NONE");
        return;
    } else if (action.equalsIgnoreCase("certs")) {
        try {
            X509Certificate cert = GlobalEntries.getGlobalEntries().getConfigManager().getCertificate(this.jwtSigningKeyName);
            JsonWebKey jwk = JsonWebKey.Factory.newJwk(cert.getPublicKey());
            String keyID = buildKID(cert);
            jwk.setKeyId(keyID);
            jwk.setUse("sig");
            jwk.setAlgorithm("RS256");
            response.setContentType("application/json");
            response.getWriter().print(new JsonWebKeySet(jwk).toJson());
            AccessLog.log(AccessEvent.AzSuccess, holder.getApp(), (HttpServletRequest) request, ac.getAuthInfo(), "NONE");
            return;
        } catch (JoseException e) {
            throw new ServletException("Could not generate jwt", e);
        }
    } else if (action.equalsIgnoreCase("auth")) {
        String clientID = request.getParameter("client_id");
        String responseCode = request.getParameter("response_type");
        String scope = request.getParameter("scope");
        String redirectURI = request.getParameter("redirect_uri");
        String state = request.getParameter("state");
        String nonce = request.getParameter("nonce");
        OpenIDConnectTransaction transaction = new OpenIDConnectTransaction();
        transaction.setClientID(clientID);
        transaction.setResponseCode(responseCode);
        transaction.setNonce(nonce);
        StringTokenizer toker = new StringTokenizer(scope, " ", false);
        while (toker.hasMoreTokens()) {
            String token = toker.nextToken();
            transaction.getScope().add(token);
        }
        transaction.setRedirectURI(redirectURI);
        transaction.setState(state);
        OpenIDConnectTrust trust = trusts.get(clientID);
        if (trust == null) {
            StringBuffer b = new StringBuffer();
            b.append(redirectURI).append("?error=unauthorized_client");
            logger.warn("Trust '" + clientID + "' not found");
            response.sendRedirect(b.toString());
            return;
        }
        if (trust.isVerifyRedirect()) {
            if (!trust.getRedirectURI().contains(redirectURI)) {
                StringBuffer b = new StringBuffer();
                b.append(redirectURI).append("?error=unauthorized_client");
                logger.warn("Invalid redirect");
                AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, ac.getAuthInfo(), "NONE");
                response.sendRedirect(b.toString());
                return;
            }
            transaction.setRedirectURI(redirectURI);
        } else {
            transaction.setRedirectURI(redirectURI);
        }
        if (this.scopes == null) {
            if (transaction.getScope().size() == 0 || !transaction.getScope().get(0).equals("openid")) {
                StringBuffer b = new StringBuffer();
                b.append(transaction.getRedirectURI()).append("?error=invalid_scope");
                logger.warn("First scope not openid");
                AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, ac.getAuthInfo(), "NONE");
                response.sendRedirect(b.toString());
                return;
            } else {
                // we don't need the openid scope anymore
                transaction.getScope().remove(0);
            }
        } else {
            for (String indvScope : transaction.getScope()) {
                if (!this.scopes.contains(indvScope)) {
                    StringBuffer b = new StringBuffer();
                    b.append(transaction.getRedirectURI()).append("?error=invalid_scope");
                    logger.warn(new StringBuilder().append("Scope '").append(indvScope).append("' not recognized"));
                    AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, ac.getAuthInfo(), "NONE");
                    response.sendRedirect(b.toString());
                    return;
                }
            }
        }
        String authChain = trust.getAuthChain();
        if (authChain == null) {
            StringBuffer b = new StringBuffer();
            b.append("IdP does not have an authenticaiton chain configured");
            throw new ServletException(b.toString());
        }
        HttpSession session = request.getSession();
        AuthInfo authData = ((AuthController) session.getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
        AuthChainType act = holder.getConfig().getAuthChains().get(authChain);
        session.setAttribute(OpenIDConnectIdP.TRANSACTION_DATA, transaction);
        if (authData == null || !authData.isAuthComplete() && !(authData.getAuthLevel() < act.getLevel())) {
            nextAuth(request, response, session, false, act);
        } else {
            if (authData.getAuthLevel() < act.getLevel()) {
                // step up authentication, clear existing auth data
                session.removeAttribute(ProxyConstants.AUTH_CTL);
                holder.getConfig().createAnonUser(session);
                nextAuth(request, response, session, false, act);
            } else {
                StringBuffer b = genFinalURL(request);
                response.sendRedirect(b.toString());
            // TODO if session already exists extend the life of the id_token
            }
        }
    } else if (action.contentEquals("completefed")) {
        this.completeFederation(request, response);
    } else if (action.equalsIgnoreCase("userinfo")) {
        try {
            processUserInfoRequest(request, response);
        } catch (Exception e) {
            throw new ServletException("Could not process userinfo request", e);
        }
    }
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) OpenIDConnectConfig(com.tremolosecurity.idp.providers.oidc.model.OpenIDConnectConfig) GsonBuilder(com.google.gson.GsonBuilder) JoseException(org.jose4j.lang.JoseException) HttpSession(javax.servlet.http.HttpSession) JsonWebKey(org.jose4j.jwk.JsonWebKey) Gson(com.google.gson.Gson) JsonWebKeySet(org.jose4j.jwk.JsonWebKeySet) AuthController(com.tremolosecurity.proxy.auth.AuthController) X509Certificate(java.security.cert.X509Certificate) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) LDAPException(com.novell.ldap.LDAPException) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) IOException(java.io.IOException) ServletException(javax.servlet.ServletException) URISyntaxException(java.net.URISyntaxException) InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) JoseException(org.jose4j.lang.JoseException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ParseException(org.json.simple.parser.ParseException) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) MalformedURLException(java.net.MalformedURLException) BadPaddingException(javax.crypto.BadPaddingException) UrlHolder(com.tremolosecurity.config.util.UrlHolder) ServletException(javax.servlet.ServletException) HttpServletRequest(javax.servlet.http.HttpServletRequest) StringTokenizer(java.util.StringTokenizer) AuthChainType(com.tremolosecurity.config.xml.AuthChainType)

Example 24 with AuthInfo

use of com.tremolosecurity.proxy.auth.AuthInfo in project OpenUnison by TremoloSecurity.

the class TokenData method completeUserLogin.

private void completeUserLogin(HttpServletRequest request, HttpServletResponse response, String code, String clientID, String clientSecret, UrlHolder holder, AuthInfo authData) throws ServletException, IOException, MalformedURLException {
    String lastMileToken = null;
    try {
        lastMileToken = this.inflate(code);
        lastMileToken = new String(org.bouncycastle.util.encoders.Base64.encode(lastMileToken.getBytes("UTF-8")));
    } catch (Exception e) {
        throw new ServletException("Could not inflate code", e);
    }
    OpenIDConnectTrust trust = this.trusts.get(clientID);
    if (!trust.isPublicEndpoint()) {
        if (!clientSecret.equals(trust.getClientSecret())) {
            AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, authData, "NONE");
            response.sendError(403);
            return;
        }
    }
    ConfigManager cfg = (ConfigManager) request.getAttribute(ProxyConstants.TREMOLO_CFG_OBJ);
    SecretKey codeKey = cfg.getSecretKey(trust.getCodeLastmileKeyName());
    com.tremolosecurity.lastmile.LastMile lmreq = new com.tremolosecurity.lastmile.LastMile();
    try {
        lmreq.loadLastMielToken(lastMileToken, codeKey);
    } catch (Exception e) {
        logger.warn("Could not decrypt code token", e);
        response.sendError(403);
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, authData, "NONE");
        return;
    }
    if (!lmreq.isValid()) {
        response.sendError(403);
        logger.warn("Could not validate code token");
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), (HttpServletRequest) request, authData, "NONE");
        return;
    }
    Attribute dn = null;
    Attribute scopes = null;
    Attribute nonce = null;
    Attribute authChainName = null;
    for (Attribute attr : lmreq.getAttributes()) {
        if (attr.getName().equalsIgnoreCase("dn")) {
            dn = attr;
        } else if (attr.getName().equalsIgnoreCase("scope")) {
            scopes = attr;
        } else if (attr.getName().equalsIgnoreCase("nonce")) {
            nonce = attr;
        } else if (attr.getName().equalsIgnoreCase("authChainName")) {
            authChainName = attr;
        }
    }
    ConfigManager cfgMgr = (ConfigManager) request.getAttribute(ProxyConstants.TREMOLO_CFG_OBJ);
    DateTime now = new DateTime();
    DateTime notBefore = now.minus(trust.getCodeTokenTimeToLive());
    DateTime notAfter = now.plus(trust.getCodeTokenTimeToLive());
    int authLevel = lmreq.getLoginLevel();
    String authMethod = lmreq.getAuthChain();
    try {
        lmreq = new com.tremolosecurity.lastmile.LastMile(request.getRequestURI(), notBefore, notAfter, authLevel, authMethod);
    } catch (URISyntaxException e) {
        throw new ServletException("Could not request access token", e);
    }
    OpenIDConnectAccessToken access = new OpenIDConnectAccessToken();
    /*
		lmreq.getAttributes().add(new Attribute("dn",dn.getValues().get(0)));
		SecretKey key = cfgMgr.getSecretKey(trust.getAccessLastmileKeyName());
		String accessToken = null;
		try {
			accessToken = lmreq.generateLastMileToken(key);
		} catch (Exception e) {
			throw new ServletException("Could not generate access token",e);
		}*/
    String accessToken = null;
    OidcSessionState oidcSession = createUserSession(request, clientID, holder, trust, dn.getValues().get(0), cfgMgr, access, (nonce != null ? nonce.getValues().get(0) : UUID.randomUUID().toString()), authChainName.getValues().get(0));
    access.setRefresh_token(oidcSession.getRefreshToken());
    Gson gson = new Gson();
    String json = gson.toJson(access);
    response.setContentType("application/json");
    response.getOutputStream().write(json.getBytes("UTF-8"));
    response.getOutputStream().flush();
    if (logger.isDebugEnabled()) {
        logger.debug("Token JSON : '" + json + "'");
    }
    AuthInfo remUser = new AuthInfo();
    remUser.setUserDN(dn.getValues().get(0));
    request.getSession().setAttribute(new StringBuilder().append("OIDC_SESSION_ID_").append(this.idpName).toString(), oidcSession.getSessionID());
    AccessLog.log(AccessEvent.AzSuccess, holder.getApp(), (HttpServletRequest) request, remUser, "NONE");
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) Attribute(com.tremolosecurity.saml.Attribute) LDAPAttribute(com.novell.ldap.LDAPAttribute) Gson(com.google.gson.Gson) URISyntaxException(java.net.URISyntaxException) ProvisioningException(com.tremolosecurity.provisioning.core.ProvisioningException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) InvalidKeyException(java.security.InvalidKeyException) LDAPException(com.novell.ldap.LDAPException) InvalidAlgorithmParameterException(java.security.InvalidAlgorithmParameterException) IOException(java.io.IOException) ServletException(javax.servlet.ServletException) URISyntaxException(java.net.URISyntaxException) InvalidJwtException(org.jose4j.jwt.consumer.InvalidJwtException) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) JoseException(org.jose4j.lang.JoseException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ParseException(org.json.simple.parser.ParseException) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) MalformedURLException(java.net.MalformedURLException) BadPaddingException(javax.crypto.BadPaddingException) ConfigManager(com.tremolosecurity.config.util.ConfigManager) DateTime(org.joda.time.DateTime) ServletException(javax.servlet.ServletException) HttpServletRequest(javax.servlet.http.HttpServletRequest) SecretKey(javax.crypto.SecretKey) OidcSessionState(com.tremolosecurity.idp.providers.oidc.model.OidcSessionState)

Example 25 with AuthInfo

use of com.tremolosecurity.proxy.auth.AuthInfo in project OpenUnison by TremoloSecurity.

the class TokenPostAuth method runAfterSuccessfulAuthentication.

@Override
public void runAfterSuccessfulAuthentication(HttpServletRequest req, HttpServletResponse resp, UrlHolder holder, AuthChainType act, RequestHolder reqHolder, AuthController actl, NextSys next) throws IOException, ServletException {
    String subjectUid;
    String amr;
    HttpSession session = req.getSession();
    AuthInfo authData = ((AuthController) session.getAttribute(ProxyConstants.AUTH_CTL)).getAuthInfo();
    if (!azSys.checkRules(authData, GlobalEntries.getGlobalEntries().getConfigManager(), trust.getClientAzRules(), new HashMap<String, Object>())) {
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, "client not authorized for token exchange");
        resp.sendError(403);
        return;
    }
    if (!trust.getAllowedAudiences().contains(stsRequest.getAudience())) {
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("Audience '").append(stsRequest.getAudience()).append("' is not an authorized audience for sts '").append(trust.getTrustName()).append("'").toString());
        resp.sendError(403);
        return;
    }
    OpenIDConnectTrust targetTrust = idp.getTrusts().get(stsRequest.getAudience());
    if (targetTrust == null) {
        logger.warn(new StringBuilder().append("Audience '").append(stsRequest.getAudience()).append("' does not exist").toString());
        resp.sendError(404);
        return;
    }
    X509Certificate sigCert = GlobalEntries.getGlobalEntries().getConfigManager().getCertificate(idp.getJwtSigningKeyName());
    if (sigCert == null) {
        logger.error(new StringBuilder().append("JWT Signing Certificate '").append(idp.getJwtSigningKeyName()).append("' does not exist").toString());
        resp.sendError(500);
        return;
    }
    JsonWebSignature jws = new JsonWebSignature();
    try {
        jws.setCompactSerialization(stsRequest.getSubjectToken());
        jws.setKey(sigCert.getPublicKey());
        if (!jws.verifySignature()) {
            AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("Invalid subject_token signature").toString());
            resp.sendError(403);
            return;
        }
        String json = jws.getPayload();
        JSONObject obj = (JSONObject) new JSONParser().parse(json);
        long exp = ((Long) obj.get("exp")) * 1000L;
        long nbf = ((Long) obj.get("nbf")) * 1000L;
        if (new DateTime(exp).isBeforeNow()) {
            AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("subject_token has expired").toString());
            resp.sendError(403);
            return;
        }
        if (new DateTime(nbf).isAfterNow()) {
            AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("subject_token is not yet valid").toString());
            resp.sendError(403);
            return;
        }
        StringBuffer issuer = new StringBuffer();
        // issuer.append(cfg.getAuthIdPPath()).append(this.idpName);
        issuer.append(holder.getApp().getUrls().getUrl().get(0).getUri());
        String issuerUrl = ProxyTools.getInstance().getFqdnUrl(issuer.toString(), req);
        if (!((String) obj.get("iss")).equals(issuerUrl)) {
            AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("subject_token has an invalid issuer").toString());
            resp.sendError(403);
            return;
        }
        subjectUid = (String) obj.get("sub");
        if (subjectUid == null) {
            logger.error("Subject has no sub claim");
            resp.sendError(422);
            return;
        }
        JSONArray amrs = (JSONArray) obj.get("amr");
        if (amrs == null) {
            logger.warn("subject_token does not contain an amr claim");
            resp.sendError(422);
            return;
        }
        amr = (String) amrs.get(0);
    } catch (JoseException | ParseException e) {
        throw new ServletException("Could not verify subject JWT", e);
    }
    // load the user
    String uidAttribute = idp.getUidAttributeFromMap();
    if (uidAttribute == null) {
        logger.error(new StringBuilder().append("IdP ").append(holder.getApp().getName()).append(" does not have a sub attribute mapped to a user attribute").toString());
        resp.sendError(500);
        return;
    }
    String authChainName = idp.getAmrToAuthChain().get(amr);
    if (authChainName == null) {
        logger.warn(new StringBuilder("subject_token amr '").append(amr).append("' does not map to any authentication chains").toString());
        resp.sendError(422);
        return;
    }
    AuthInfo subjectForAz = this.lookupUser(session, GlobalEntries.getGlobalEntries().getConfigManager().getMyVD(), uidAttribute, act, subjectUid, authChainName);
    if (subjectForAz == null) {
        logger.error(new StringBuilder().append("STS exchange for sub '").append(subjectUid).append("' failed because user not found"));
        resp.sendError(422);
        return;
    }
    // with a subject in hand, authorize that we're able to take care of
    if (!azSys.checkRules(subjectForAz, GlobalEntries.getGlobalEntries().getConfigManager(), trust.getSubjectAzRules(), new HashMap<String, Object>())) {
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("client not authorized to exchange token for subject '").append(subjectUid).append("'").toString());
        resp.sendError(403);
        return;
    }
    if (this.stsRequest.isImpersonation() && !trust.isStsImpersonation()) {
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("client '").append(trust.getTrustName()).append("' authorized for impersonation").toString());
        resp.sendError(403);
        return;
    }
    if (this.stsRequest.isDelegation() && !trust.isStsDelegation()) {
        AccessLog.log(AccessEvent.AzFail, holder.getApp(), req, authData, new StringBuilder().append("client '").append(trust.getTrustName()).append("' authorized for delegation").toString());
        resp.sendError(403);
        return;
    }
    OpenIDConnectAccessToken access = new OpenIDConnectAccessToken();
    OidcSessionState oidcSession = idp.createUserSession(req, stsRequest.getAudience(), holder, targetTrust, subjectForAz.getUserDN(), GlobalEntries.getGlobalEntries().getConfigManager(), access, UUID.randomUUID().toString(), subjectForAz.getAuthChain());
    if (this.stsRequest.isImpersonation()) {
        AccessLog.log(AccessEvent.AzSuccess, holder.getApp(), req, authData, new StringBuilder().append("client '").append(trust.getTrustName()).append("' impersonating '").append(subjectUid).append("', jti : '").append(access.getIdTokenId()).append("'").toString());
    }
    String idtoken = access.getId_token();
    access.setRefresh_token(oidcSession.getRefreshToken());
    Gson gson = new Gson();
    String json = gson.toJson(access);
    resp.setContentType("application/json");
    resp.getOutputStream().write(json.getBytes("UTF-8"));
    resp.getOutputStream().flush();
    if (logger.isDebugEnabled()) {
        logger.debug("Token JSON : '" + json + "'");
    }
}
Also used : AuthInfo(com.tremolosecurity.proxy.auth.AuthInfo) HashMap(java.util.HashMap) HttpSession(javax.servlet.http.HttpSession) JoseException(org.jose4j.lang.JoseException) JSONArray(org.json.simple.JSONArray) Gson(com.google.gson.Gson) AuthController(com.tremolosecurity.proxy.auth.AuthController) X509Certificate(java.security.cert.X509Certificate) DateTime(org.joda.time.DateTime) ServletException(javax.servlet.ServletException) JsonWebSignature(org.jose4j.jws.JsonWebSignature) JSONObject(org.json.simple.JSONObject) JSONParser(org.json.simple.parser.JSONParser) ParseException(org.json.simple.parser.ParseException) OidcSessionState(com.tremolosecurity.idp.providers.oidc.model.OidcSessionState)

Aggregations

AuthInfo (com.tremolosecurity.proxy.auth.AuthInfo)71 AuthController (com.tremolosecurity.proxy.auth.AuthController)59 Attribute (com.tremolosecurity.saml.Attribute)46 LDAPAttribute (com.novell.ldap.LDAPAttribute)27 IOException (java.io.IOException)25 ServletException (javax.servlet.ServletException)24 HttpSession (javax.servlet.http.HttpSession)23 Gson (com.google.gson.Gson)22 LDAPException (com.novell.ldap.LDAPException)22 LDAPSearchResults (com.novell.ldap.LDAPSearchResults)22 LDAPEntry (com.novell.ldap.LDAPEntry)19 HashMap (java.util.HashMap)19 UrlHolder (com.tremolosecurity.config.util.UrlHolder)18 ProvisioningException (com.tremolosecurity.provisioning.core.ProvisioningException)18 MalformedURLException (java.net.MalformedURLException)15 AuthChainType (com.tremolosecurity.config.xml.AuthChainType)14 ArrayList (java.util.ArrayList)14 AzSys (com.tremolosecurity.proxy.auth.AzSys)12 UnsupportedEncodingException (java.io.UnsupportedEncodingException)11 HttpServletRequest (javax.servlet.http.HttpServletRequest)11