Пример #1
0
 @Override
 public Response keycloakInitiatedBrowserLogout(
     UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
   if (getConfig().getLogoutUrl() == null || getConfig().getLogoutUrl().trim().equals(""))
     return null;
   String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
   if (idToken != null && getConfig().isBackchannelSupported()) {
     backchannelLogout(userSession, idToken);
     return null;
   } else {
     String sessionId = userSession.getId();
     UriBuilder logoutUri =
         UriBuilder.fromUri(getConfig().getLogoutUrl()).queryParam("state", sessionId);
     if (idToken != null) logoutUri.queryParam("id_token_hint", idToken);
     String redirect =
         RealmsResource.brokerUrl(uriInfo)
             .path(IdentityBrokerService.class, "getEndpoint")
             .path(OIDCEndpoint.class, "logoutResponse")
             .build(realm.getName(), getConfig().getAlias())
             .toString();
     logoutUri.queryParam("post_logout_redirect_uri", redirect);
     Response response = Response.status(302).location(logoutUri.build()).build();
     return response;
   }
 }
Пример #2
0
  /**
   * Get offline sessions for client
   *
   * <p>Returns a list of offline user sessions associated with this client
   *
   * @param firstResult Paging offset
   * @param maxResults Maximum results size (defaults to 100)
   * @return
   */
  @Path("offline-sessions")
  @GET
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public List<UserSessionRepresentation> getOfflineUserSessions(
      @QueryParam("first") Integer firstResult, @QueryParam("max") Integer maxResults) {
    auth.requireView();

    if (client == null) {
      throw new NotFoundException("Could not find client");
    }

    firstResult = firstResult != null ? firstResult : -1;
    maxResults = maxResults != null ? maxResults : Constants.DEFAULT_MAX_RESULTS;
    List<UserSessionRepresentation> sessions = new ArrayList<UserSessionRepresentation>();
    List<UserSessionModel> userSessions =
        session
            .sessions()
            .getOfflineUserSessions(client.getRealm(), client, firstResult, maxResults);
    for (UserSessionModel userSession : userSessions) {
      UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(userSession);

      // Update lastSessionRefresh with the timestamp from clientSession
      for (ClientSessionModel clientSession : userSession.getClientSessions()) {
        if (client.getId().equals(clientSession.getClient().getId())) {
          rep.setLastAccess(Time.toMillis(clientSession.getTimestamp()));
          break;
        }
      }

      sessions.add(rep);
    }
    return sessions;
  }
Пример #3
0
  public static void attachClientSession(
      UserSessionModel session, ClientSessionModel clientSession) {
    if (clientSession.getUserSession() != null) {
      return;
    }

    UserModel user = session.getUser();
    clientSession.setUserSession(session);
    Set<String> requestedRoles = new HashSet<String>();
    // todo scope param protocol independent
    for (RoleModel r : TokenManager.getAccess(null, clientSession.getClient(), user)) {
      requestedRoles.add(r.getId());
    }
    clientSession.setRoles(requestedRoles);

    Set<String> requestedProtocolMappers = new HashSet<String>();
    for (ProtocolMapperModel protocolMapper : clientSession.getClient().getProtocolMappers()) {
      if (protocolMapper.getProtocol().equals(clientSession.getAuthMethod())) {
        requestedProtocolMappers.add(protocolMapper.getId());
      }
    }
    clientSession.setProtocolMappers(requestedProtocolMappers);

    Map<String, String> transferredNotes = clientSession.getUserSessionNotes();
    for (Map.Entry<String, String> entry : transferredNotes.entrySet()) {
      session.setNote(entry.getKey(), entry.getValue());
    }
  }
Пример #4
0
  /**
   * Get offline sessions associated with the user and client
   *
   * @param id User id
   * @return
   */
  @Path("{id}/offline-sessions/{clientId}")
  @GET
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public List<UserSessionRepresentation> getSessions(
      final @PathParam("id") String id, final @PathParam("clientId") String clientId) {
    auth.requireView();
    UserModel user = session.users().getUserById(id, realm);
    if (user == null) {
      throw new NotFoundException("User not found");
    }
    ClientModel client = realm.getClientById(clientId);
    if (client == null) {
      throw new NotFoundException("Client not found");
    }
    List<UserSessionModel> sessions =
        new UserSessionManager(session).findOfflineSessions(realm, client, user);
    List<UserSessionRepresentation> reps = new ArrayList<UserSessionRepresentation>();
    for (UserSessionModel session : sessions) {
      UserSessionRepresentation rep = ModelToRepresentation.toRepresentation(session);

      // Update lastSessionRefresh with the timestamp from clientSession
      for (ClientSessionModel clientSession : session.getClientSessions()) {
        if (clientId.equals(clientSession.getClient().getId())) {
          rep.setLastAccess(Time.toMillis(clientSession.getTimestamp()));
          break;
        }
      }

      reps.add(rep);
    }
    return reps;
  }
Пример #5
0
 @Path("sessions/{session}")
 @DELETE
 public void deleteSession(@PathParam("session") String sessionId) {
   UserSessionModel session = realm.getUserSession(sessionId);
   if (session == null) throw new NotFoundException("Sesssion not found");
   realm.removeUserSession(session);
   new ResourceAdminManager().logoutSession(uriInfo.getRequestUri(), realm, session.getId());
 }
Пример #6
0
 @Override
 public void attachUserSession(
     UserSessionModel userSession,
     ClientSessionModel clientSession,
     BrokeredIdentityContext context) {
   AccessTokenResponse tokenResponse =
       (AccessTokenResponse) context.getContextData().get(FEDERATED_ACCESS_TOKEN_RESPONSE);
   userSession.setNote(FEDERATED_ACCESS_TOKEN, tokenResponse.getToken());
   userSession.setNote(FEDERATED_ID_TOKEN, tokenResponse.getIdToken());
 }
Пример #7
0
  /**
   * Impersonate the user
   *
   * @param id User id
   * @return
   */
  @Path("{id}/impersonation")
  @POST
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public Map<String, Object> impersonate(final @PathParam("id") String id) {
    auth.init(RealmAuth.Resource.IMPERSONATION);
    auth.requireManage();
    UserModel user = session.users().getUserById(id, realm);
    if (user == null) {
      throw new NotFoundException("User not found");
    }
    RealmModel authenticatedRealm = auth.getAuth().getRealm();
    // if same realm logout before impersonation
    boolean sameRealm = false;
    if (authenticatedRealm.getId().equals(realm.getId())) {
      sameRealm = true;
      UserSessionModel userSession =
          session
              .sessions()
              .getUserSession(authenticatedRealm, auth.getAuth().getToken().getSessionState());
      AuthenticationManager.expireIdentityCookie(realm, uriInfo, clientConnection);
      AuthenticationManager.expireRememberMeCookie(realm, uriInfo, clientConnection);
      AuthenticationManager.backchannelLogout(
          session, authenticatedRealm, userSession, uriInfo, clientConnection, headers, true);
    }
    EventBuilder event = new EventBuilder(realm, session, clientConnection);

    UserSessionModel userSession =
        session
            .sessions()
            .createUserSession(
                realm,
                user,
                user.getUsername(),
                clientConnection.getRemoteAddr(),
                "impersonate",
                false,
                null,
                null);
    AuthenticationManager.createLoginCookie(
        realm, userSession.getUser(), userSession, uriInfo, clientConnection);
    URI redirect = AccountService.accountServiceApplicationPage(uriInfo).build(realm.getName());
    Map<String, Object> result = new HashMap<>();
    result.put("sameRealm", sameRealm);
    result.put("redirect", redirect.toString());
    event
        .event(EventType.IMPERSONATE)
        .session(userSession)
        .user(user)
        .detail(Details.IMPERSONATOR_REALM, authenticatedRealm.getName())
        .detail(Details.IMPERSONATOR, auth.getAuth().getUser().getUsername())
        .success();

    return result;
  }
Пример #8
0
  public static void dettachClientSession(
      UserSessionProvider sessions, RealmModel realm, ClientSessionModel clientSession) {
    UserSessionModel userSession = clientSession.getUserSession();
    if (userSession == null) {
      return;
    }

    clientSession.setUserSession(null);
    clientSession.setRoles(null);
    clientSession.setProtocolMappers(null);

    if (userSession.getClientSessions().isEmpty()) {
      sessions.removeUserSession(realm, userSession);
    }
  }
Пример #9
0
 protected AccessToken initToken(
     RealmModel realm,
     ClientModel client,
     UserModel user,
     UserSessionModel session,
     ClientSessionModel clientSession) {
   AccessToken token = new AccessToken();
   if (clientSession != null) token.clientSession(clientSession.getId());
   token.id(KeycloakModelUtils.generateId());
   token.subject(user.getId());
   token.audience(client.getClientId());
   token.issuedNow();
   token.issuedFor(client.getClientId());
   token.issuer(clientSession.getNote(OIDCLoginProtocol.ISSUER));
   if (session != null) {
     token.setSessionState(session.getId());
   }
   if (realm.getAccessTokenLifespan() > 0) {
     token.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
   }
   Set<String> allowedOrigins = client.getWebOrigins();
   if (allowedOrigins != null) {
     token.setAllowedOrigins(allowedOrigins);
   }
   return token;
 }
Пример #10
0
 protected String getNameId(
     String nameIdFormat, ClientSessionModel clientSession, UserSessionModel userSession) {
   if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_EMAIL.get())) {
     return userSession.getUser().getEmail();
   } else if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_TRANSIENT.get())) {
     // "G-" stands for "generated" Add this for the slight possibility of collisions.
     return "G-" + UUID.randomUUID().toString();
   } else if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_PERSISTENT.get())) {
     return getPersistentNameId(clientSession, userSession);
   } else if (nameIdFormat.equals(JBossSAMLURIConstants.NAMEID_FORMAT_UNSPECIFIED.get())) {
     // TODO: Support for persistent NameID (pseudo-random identifier persisted in user object)
     return userSession.getUser().getUsername();
   } else {
     return userSession.getUser().getUsername();
   }
 }
Пример #11
0
 @Override
 public void backchannelLogout(UserSessionModel userSession, UriInfo uriInfo, RealmModel realm) {
   if (getConfig().getLogoutUrl() == null
       || getConfig().getLogoutUrl().trim().equals("")
       || !getConfig().isBackchannelSupported()) return;
   String idToken = userSession.getNote(FEDERATED_ID_TOKEN);
   if (idToken == null) return;
   backchannelLogout(userSession, idToken);
 }
Пример #12
0
  @Override
  public Response finishLogout(UserSessionModel userSession) {
    String redirectUri = userSession.getNote(OIDCLoginProtocol.LOGOUT_REDIRECT_URI);
    String state = userSession.getNote(OIDCLoginProtocol.LOGOUT_STATE_PARAM);
    event.event(EventType.LOGOUT);
    if (redirectUri != null) {
      event.detail(Details.REDIRECT_URI, redirectUri);
    }
    event.user(userSession.getUser()).session(userSession).success();

    if (redirectUri != null) {
      UriBuilder uriBuilder = UriBuilder.fromUri(redirectUri);
      if (state != null) uriBuilder.queryParam(STATE_PARAM, state);
      return Response.status(302).location(uriBuilder.build()).build();
    } else {
      return Response.ok().build();
    }
  }
Пример #13
0
 @GET
 @Path("logout_response")
 public Response logoutResponse(@Context UriInfo uriInfo, @QueryParam("state") String state) {
   UserSessionModel userSession = session.sessions().getUserSession(realm, state);
   if (userSession == null) {
     logger.error("no valid user session");
     EventBuilder event = new EventBuilder(realm, session, clientConnection);
     event.event(EventType.LOGOUT);
     event.error(Errors.USER_SESSION_NOT_FOUND);
     return ErrorPage.error(session, Messages.IDENTITY_PROVIDER_UNEXPECTED_ERROR);
   }
   if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
     logger.error("usersession in different state");
     EventBuilder event = new EventBuilder(realm, session, clientConnection);
     event.event(EventType.LOGOUT);
     event.error(Errors.USER_SESSION_NOT_FOUND);
     return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
   }
   return AuthenticationManager.finishBrowserLogout(
       session, realm, userSession, uriInfo, clientConnection, headers);
 }
Пример #14
0
  @Override
  public Response finishLogout(UserSessionModel userSession) {
    logger.debug("finishLogout");
    String logoutBindingUri = userSession.getNote(SAML_LOGOUT_BINDING_URI);
    if (logoutBindingUri == null) {
      logger.error(
          "Can't finish SAML logout as there is no logout binding set.  Please configure the logout service url in the admin console for your client applications.");
      return ErrorPage.error(session, Messages.FAILED_LOGOUT);
    }
    String logoutRelayState = userSession.getNote(SAML_LOGOUT_RELAY_STATE);
    SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
    builder.logoutRequestID(userSession.getNote(SAML_LOGOUT_REQUEST_ID));
    builder.destination(logoutBindingUri);
    builder.issuer(getResponseIssuer(realm));
    JaxrsSAML2BindingBuilder binding = new JaxrsSAML2BindingBuilder();
    binding.relayState(logoutRelayState);
    String signingAlgorithm = userSession.getNote(SAML_LOGOUT_SIGNATURE_ALGORITHM);
    if (signingAlgorithm != null) {
      SignatureAlgorithm algorithm = SignatureAlgorithm.valueOf(signingAlgorithm);
      String canonicalization = userSession.getNote(SAML_LOGOUT_CANONICALIZATION);
      if (canonicalization != null) {
        binding.canonicalizationMethod(canonicalization);
      }
      KeyManager.ActiveKey keys = session.keys().getActiveKey(realm);
      binding
          .signatureAlgorithm(algorithm)
          .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
          .signDocument();
    }

    try {
      return buildLogoutResponse(userSession, logoutBindingUri, builder, binding);
    } catch (ConfigurationException e) {
      throw new RuntimeException(e);
    } catch (ProcessingException e) {
      throw new RuntimeException(e);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
 @Override
 public void transformAttributeStatement(
     AttributeStatementType attributeStatement,
     ProtocolMapperModel mappingModel,
     KeycloakSession session,
     UserSessionModel userSession,
     ClientSessionModel clientSession) {
   UserModel user = userSession.getUser();
   String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE);
   String attributeValue = user.getFirstAttribute(attributeName);
   if (attributeValue == null) return;
   AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue);
 }
Пример #16
0
  private void initEvent(ClientSessionModel clientSession) {
    event
        .event(EventType.LOGIN)
        .client(clientSession.getClient())
        .user(clientSession.getUserSession().getUser())
        .session(clientSession.getUserSession().getId())
        .detail(Details.CODE_ID, clientSession.getId())
        .detail(Details.REDIRECT_URI, clientSession.getRedirectUri())
        .detail(
            Details.USERNAME,
            clientSession.getNote(AbstractUsernameFormAuthenticator.ATTEMPTED_USERNAME))
        .detail(Details.RESPONSE_TYPE, "code");

    UserSessionModel userSession = clientSession.getUserSession();

    if (userSession != null) {
      event.detail(Details.AUTH_METHOD, userSession.getAuthMethod());
      event.detail(Details.USERNAME, userSession.getLoginUsername());
      if (userSession.isRememberMe()) {
        event.detail(Details.REMEMBER_ME, "true");
      }
    }
  }
Пример #17
0
    protected Response handleSamlResponse(String samlResponse, String relayState) {
      event.event(EventType.LOGOUT);
      SAMLDocumentHolder holder = extractResponseDocument(samlResponse);
      StatusResponseType statusResponse = (StatusResponseType) holder.getSamlObject();
      // validate destination
      if (statusResponse.getDestination() != null
          && !uriInfo.getAbsolutePath().toString().equals(statusResponse.getDestination())) {
        event.detail(Details.REASON, "invalid_destination");
        event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
        return ErrorPage.error(session, Messages.INVALID_REQUEST);
      }

      AuthenticationManager.AuthResult authResult =
          authManager.authenticateIdentityCookie(session, realm, false);
      if (authResult == null) {
        logger.warn("Unknown saml response.");
        event.event(EventType.LOGOUT);
        event.error(Errors.INVALID_TOKEN);
        return ErrorPage.error(session, Messages.INVALID_REQUEST);
      }
      // assume this is a logout response
      UserSessionModel userSession = authResult.getSession();
      if (userSession.getState() != UserSessionModel.State.LOGGING_OUT) {
        logger.warn("Unknown saml response.");
        logger.warn("UserSession is not tagged as logging out.");
        event.event(EventType.LOGOUT);
        event.error(Errors.INVALID_SAML_LOGOUT_RESPONSE);
        return ErrorPage.error(session, Messages.INVALID_REQUEST);
      }
      logger.debug("logout response");
      Response response =
          authManager.browserLogout(
              session, realm, userSession, uriInfo, clientConnection, headers);
      event.success();
      return response;
    }
Пример #18
0
 protected void backchannelLogout(UserSessionModel userSession, String idToken) {
   String sessionId = userSession.getId();
   UriBuilder logoutUri =
       UriBuilder.fromUri(getConfig().getLogoutUrl()).queryParam("state", sessionId);
   logoutUri.queryParam("id_token_hint", idToken);
   String url = logoutUri.build().toString();
   try {
     int status = JsonSimpleHttp.doGet(url).asStatus();
     boolean success = status >= 200 && status < 400;
     if (!success) {
       logger.warn("Failed backchannel broker logout to: " + url);
     }
   } catch (Exception e) {
     logger.warn("Failed backchannel broker logout to: " + url, e);
   }
 }
Пример #19
0
  @Path("email-verification")
  @GET
  public Response emailVerification(
      @QueryParam("code") String code, @QueryParam("key") String key) {
    event.event(EventType.VERIFY_EMAIL);
    if (key != null) {
      Checks checks = new Checks();
      if (!checks.verifyCode(key, ClientSessionModel.Action.VERIFY_EMAIL.name())) {
        return checks.response;
      }
      ClientSessionCode accessCode = checks.clientCode;
      ClientSessionModel clientSession = accessCode.getClientSession();
      UserSessionModel userSession = clientSession.getUserSession();
      UserModel user = userSession.getUser();
      initEvent(clientSession);
      user.setEmailVerified(true);

      user.removeRequiredAction(RequiredAction.VERIFY_EMAIL);

      event.event(EventType.VERIFY_EMAIL).detail(Details.EMAIL, user.getEmail()).success();

      String actionCookieValue = getActionCookie();
      if (actionCookieValue == null || !actionCookieValue.equals(userSession.getId())) {
        session.sessions().removeClientSession(realm, clientSession);
        return session
            .getProvider(LoginFormsProvider.class)
            .setSuccess(Messages.EMAIL_VERIFIED)
            .createInfoPage();
      }

      event = event.clone().removeDetail(Details.EMAIL).event(EventType.LOGIN);

      return AuthenticationManager.nextActionAfterAuthentication(
          session, userSession, clientSession, clientConnection, request, uriInfo, event);
    } else {
      Checks checks = new Checks();
      if (!checks.verifyCode(code, ClientSessionModel.Action.VERIFY_EMAIL.name())) {
        return checks.response;
      }
      ClientSessionCode accessCode = checks.clientCode;
      ClientSessionModel clientSession = accessCode.getClientSession();
      UserSessionModel userSession = clientSession.getUserSession();
      initEvent(clientSession);

      createActionCookie(realm, uriInfo, clientConnection, userSession.getId());

      return session
          .getProvider(LoginFormsProvider.class)
          .setClientSessionCode(accessCode.getCode())
          .setUser(userSession.getUser())
          .createResponse(RequiredAction.VERIFY_EMAIL);
    }
  }
Пример #20
0
 public AccessTokenResponseBuilder generateIDToken() {
   if (accessToken == null) {
     throw new IllegalStateException("accessToken not set");
   }
   idToken = new IDToken();
   idToken.id(KeycloakModelUtils.generateId());
   idToken.subject(accessToken.getSubject());
   idToken.audience(client.getClientId());
   idToken.issuedNow();
   idToken.issuedFor(accessToken.getIssuedFor());
   idToken.issuer(accessToken.getIssuer());
   idToken.setSessionState(accessToken.getSessionState());
   if (realm.getAccessTokenLifespan() > 0) {
     idToken.expiration(Time.currentTime() + realm.getAccessTokenLifespan());
   }
   transformIDToken(
       session, idToken, realm, client, userSession.getUser(), userSession, clientSession);
   return this;
 }
Пример #21
0
  /**
   * Attempts to retrieve the persistent type NameId as follows:
   *
   * <ol>
   *   <li>saml.persistent.name.id.for.$clientId user attribute
   *   <li>saml.persistent.name.id.for.* user attribute
   *   <li>G-$randomUuid
   * </ol>
   *
   * If a randomUuid is generated, an attribute for the given saml.persistent.name.id.for.$clientId
   * will be generated, otherwise no state change will occur with respect to the user's attributes.
   *
   * @return the user's persistent NameId
   */
  protected String getPersistentNameId(
      final ClientSessionModel clientSession, final UserSessionModel userSession) {
    // attempt to retrieve the UserID for the client-specific attribute
    final UserModel user = userSession.getUser();
    final String clientNameId =
        String.format(
            "%s.%s", SAML_PERSISTENT_NAME_ID_FOR, clientSession.getClient().getClientId());
    String samlPersistentNameId = user.getFirstAttribute(clientNameId);
    if (samlPersistentNameId != null) {
      return samlPersistentNameId;
    }

    // check for a wildcard attribute
    final String wildcardNameId = String.format("%s.*", SAML_PERSISTENT_NAME_ID_FOR);
    samlPersistentNameId = user.getFirstAttribute(wildcardNameId);
    if (samlPersistentNameId != null) {
      return samlPersistentNameId;
    }

    // default to generated.  "G-" stands for "generated"
    samlPersistentNameId = "G-" + UUID.randomUUID().toString();
    user.setSingleAttribute(clientNameId, samlPersistentNameId);
    return samlPersistentNameId;
  }
Пример #22
0
  /**
   * OAuth grant page. You should not invoked this directly!
   *
   * @param formData
   * @return
   */
  @Path("consent")
  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  public Response processConsent(final MultivaluedMap<String, String> formData) {
    event.event(EventType.LOGIN).detail(Details.RESPONSE_TYPE, "code");

    if (!checkSsl()) {
      return ErrorPage.error(session, Messages.HTTPS_REQUIRED);
    }

    String code = formData.getFirst("code");

    ClientSessionCode accessCode = ClientSessionCode.parse(code, session, realm);
    if (accessCode == null || !accessCode.isValid(ClientSessionModel.Action.OAUTH_GRANT.name())) {
      event.error(Errors.INVALID_CODE);
      return ErrorPage.error(session, Messages.INVALID_ACCESS_CODE);
    }
    ClientSessionModel clientSession = accessCode.getClientSession();
    event.detail(Details.CODE_ID, clientSession.getId());

    String redirect = clientSession.getRedirectUri();
    UserSessionModel userSession = clientSession.getUserSession();
    UserModel user = userSession.getUser();
    ClientModel client = clientSession.getClient();

    event
        .client(client)
        .user(user)
        .detail(Details.RESPONSE_TYPE, "code")
        .detail(Details.REDIRECT_URI, redirect);

    event.detail(Details.AUTH_METHOD, userSession.getAuthMethod());
    event.detail(Details.USERNAME, userSession.getLoginUsername());
    if (userSession.isRememberMe()) {
      event.detail(Details.REMEMBER_ME, "true");
    }

    if (!AuthenticationManager.isSessionValid(realm, userSession)) {
      AuthenticationManager.backchannelLogout(
          session, realm, userSession, uriInfo, clientConnection, headers, true);
      event.error(Errors.INVALID_CODE);
      return ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE);
    }
    event.session(userSession);

    if (formData.containsKey("cancel")) {
      LoginProtocol protocol =
          session.getProvider(LoginProtocol.class, clientSession.getAuthMethod());
      protocol.setRealm(realm).setHttpHeaders(headers).setUriInfo(uriInfo);
      event.error(Errors.REJECTED_BY_USER);
      return protocol.consentDenied(clientSession);
    }

    UserConsentModel grantedConsent = user.getConsentByClient(client.getId());
    if (grantedConsent == null) {
      grantedConsent = new UserConsentModel(client);
      user.addConsent(grantedConsent);
    }
    for (RoleModel role : accessCode.getRequestedRoles()) {
      grantedConsent.addGrantedRole(role);
    }
    for (ProtocolMapperModel protocolMapper : accessCode.getRequestedProtocolMappers()) {
      if (protocolMapper.isConsentRequired() && protocolMapper.getConsentText() != null) {
        grantedConsent.addGrantedProtocolMapper(protocolMapper);
      }
    }
    user.updateConsent(grantedConsent);

    event.detail(Details.CONSENT, Details.CONSENT_VALUE_CONSENT_GRANTED);
    event.success();

    return authManager.redirectAfterSuccessfulFlow(
        session, realm, userSession, clientSession, request, uriInfo, clientConnection);
  }
Пример #23
0
 public static boolean isLogoutPostBindingForInitiator(UserSessionModel session) {
   String note = session.getNote(SamlProtocol.SAML_LOGOUT_BINDING);
   return SamlProtocol.SAML_POST_BINDING.equals(note);
 }
Пример #24
0
  public TokenValidation validateToken(
      KeycloakSession session,
      UriInfo uriInfo,
      ClientConnection connection,
      RealmModel realm,
      AccessToken oldToken,
      HttpHeaders headers)
      throws OAuthErrorException {
    UserModel user = session.users().getUserById(oldToken.getSubject(), realm);
    if (user == null) {
      throw new OAuthErrorException(
          OAuthErrorException.INVALID_GRANT, "Invalid refresh token", "Unknown user");
    }

    if (!user.isEnabled()) {
      throw new OAuthErrorException(
          OAuthErrorException.INVALID_GRANT, "User disabled", "User disabled");
    }

    UserSessionModel userSession =
        session.sessions().getUserSession(realm, oldToken.getSessionState());
    if (!AuthenticationManager.isSessionValid(realm, userSession)) {
      AuthenticationManager.backchannelLogout(
          session, realm, userSession, uriInfo, connection, headers, true);
      throw new OAuthErrorException(
          OAuthErrorException.INVALID_GRANT, "Session not active", "Session not active");
    }
    ClientSessionModel clientSession = null;
    for (ClientSessionModel clientSessionModel : userSession.getClientSessions()) {
      if (clientSessionModel.getId().equals(oldToken.getClientSession())) {
        clientSession = clientSessionModel;
        break;
      }
    }

    if (clientSession == null) {
      throw new OAuthErrorException(
          OAuthErrorException.INVALID_GRANT,
          "Client session not active",
          "Client session not active");
    }

    ClientModel client = clientSession.getClient();

    if (!client.getClientId().equals(oldToken.getIssuedFor())) {
      throw new OAuthErrorException(
          OAuthErrorException.INVALID_GRANT, "Unmatching clients", "Unmatching clients");
    }

    if (oldToken.getIssuedAt() < client.getNotBefore()) {
      throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
    }
    if (oldToken.getIssuedAt() < realm.getNotBefore()) {
      throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Stale token");
    }

    // recreate token.
    Set<RoleModel> requestedRoles = TokenManager.getAccess(null, clientSession.getClient(), user);
    AccessToken newToken =
        createClientAccessToken(
            session, requestedRoles, realm, client, user, userSession, clientSession);
    verifyAccess(oldToken, newToken);

    return new TokenValidation(user, userSession, clientSession, newToken);
  }
Пример #25
0
  public void init() {
    eventStore = session.getProvider(EventStoreProvider.class);

    account =
        session
            .getProvider(AccountProvider.class)
            .setRealm(realm)
            .setUriInfo(uriInfo)
            .setHttpHeaders(headers);

    AuthenticationManager.AuthResult authResult =
        authManager.authenticateBearerToken(session, realm, uriInfo, clientConnection, headers);
    if (authResult != null) {
      auth =
          new Auth(
              realm,
              authResult.getToken(),
              authResult.getUser(),
              client,
              authResult.getSession(),
              false);
    } else {
      authResult = authManager.authenticateIdentityCookie(session, realm);
      if (authResult != null) {
        auth =
            new Auth(
                realm,
                authResult.getToken(),
                authResult.getUser(),
                client,
                authResult.getSession(),
                true);
        updateCsrfChecks();
        account.setStateChecker(stateChecker);
      }
    }

    String requestOrigin = UriUtils.getOrigin(uriInfo.getBaseUri());

    // don't allow cors requests unless they were authenticated by an access token
    // This is to prevent CSRF attacks.
    if (auth != null && auth.isCookieAuthenticated()) {
      String origin = headers.getRequestHeaders().getFirst("Origin");
      if (origin != null && !requestOrigin.equals(origin)) {
        throw new ForbiddenException();
      }

      if (!request.getHttpMethod().equals("GET")) {
        String referrer = headers.getRequestHeaders().getFirst("Referer");
        if (referrer != null && !requestOrigin.equals(UriUtils.getOrigin(referrer))) {
          throw new ForbiddenException();
        }
      }
    }

    if (authResult != null) {
      UserSessionModel userSession = authResult.getSession();
      if (userSession != null) {
        boolean associated = false;
        for (ClientSessionModel c : userSession.getClientSessions()) {
          if (c.getClient().equals(client)) {
            auth.setClientSession(c);
            associated = true;
            break;
          }
        }
        if (!associated) {
          ClientSessionModel clientSession = session.sessions().createClientSession(realm, client);
          clientSession.setUserSession(userSession);
          auth.setClientSession(clientSession);
        }
      }

      account.setUser(auth.getUser());
    }

    boolean eventsEnabled = eventStore != null && realm.isEventsEnabled();

    // todo find out from federation if password is updatable
    account.setFeatures(realm.isIdentityFederationEnabled(), eventsEnabled, true);
  }
Пример #26
0
  /**
   * Update account password
   *
   * <p>Form params:
   *
   * <p>password - old password password-new pasword-confirm
   *
   * @param formData
   * @return
   */
  @Path("password")
  @POST
  @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
  public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
    if (auth == null) {
      return login("password");
    }

    require(AccountRoles.MANAGE_ACCOUNT);

    String action = formData.getFirst("submitAction");
    if (action != null && action.equals("Cancel")) {
      setReferrerOnPage();
      return account.createResponse(AccountPages.PASSWORD);
    }

    csrfCheck(formData);
    UserModel user = auth.getUser();

    boolean requireCurrent = isPasswordSet(user);
    account.setPasswordSet(requireCurrent);

    String password = formData.getFirst("password");
    String passwordNew = formData.getFirst("password-new");
    String passwordConfirm = formData.getFirst("password-confirm");

    if (requireCurrent) {
      if (Validation.isBlank(password)) {
        setReferrerOnPage();
        return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
      }

      UserCredentialModel cred = UserCredentialModel.password(password);
      if (!session.users().validCredentials(realm, user, cred)) {
        setReferrerOnPage();
        return account
            .setError(Messages.INVALID_PASSWORD_EXISTING)
            .createResponse(AccountPages.PASSWORD);
      }
    }

    if (Validation.isEmpty(passwordNew)) {
      setReferrerOnPage();
      return account.setError(Messages.MISSING_PASSWORD).createResponse(AccountPages.PASSWORD);
    }

    if (!passwordNew.equals(passwordConfirm)) {
      setReferrerOnPage();
      return account
          .setError(Messages.INVALID_PASSWORD_CONFIRM)
          .createResponse(AccountPages.PASSWORD);
    }

    try {
      session.users().updateCredential(realm, user, UserCredentialModel.password(passwordNew));
    } catch (ModelReadOnlyException mre) {
      setReferrerOnPage();
      return account.setError(Messages.READ_ONLY_PASSWORD).createResponse(AccountPages.PASSWORD);
    } catch (ModelException me) {
      logger.error("Failed to update password", me);
      setReferrerOnPage();
      return account
          .setError(me.getMessage(), me.getParameters())
          .createResponse(AccountPages.PASSWORD);
    } catch (Exception ape) {
      logger.error("Failed to update password", ape);
      setReferrerOnPage();
      return account.setError(ape.getMessage()).createResponse(AccountPages.PASSWORD);
    }

    List<UserSessionModel> sessions = session.sessions().getUserSessions(realm, user);
    for (UserSessionModel s : sessions) {
      if (!s.getId().equals(auth.getSession().getId())) {
        AuthenticationManager.backchannelLogout(
            session, realm, s, uriInfo, clientConnection, headers, true);
      }
    }

    event.event(EventType.UPDATE_PASSWORD).client(auth.getClient()).user(auth.getUser()).success();

    setReferrerOnPage();
    return account
        .setPasswordSet(true)
        .setSuccess(Messages.ACCOUNT_PASSWORD_UPDATED)
        .createResponse(AccountPages.PASSWORD);
  }
Пример #27
0
    protected Response logoutRequest(
        LogoutRequestType logoutRequest, ClientModel client, String relayState) {
      SamlClient samlClient = new SamlClient(client);
      // validate destination
      if (logoutRequest.getDestination() != null
          && !uriInfo.getAbsolutePath().equals(logoutRequest.getDestination())) {
        event.detail(Details.REASON, "invalid_destination");
        event.error(Errors.INVALID_SAML_LOGOUT_REQUEST);
        return ErrorPage.error(session, Messages.INVALID_REQUEST);
      }

      // authenticate identity cookie, but ignore an access token timeout as we're logging out
      // anyways.
      AuthenticationManager.AuthResult authResult =
          authManager.authenticateIdentityCookie(session, realm, false);
      if (authResult != null) {
        String logoutBinding = getBindingType();
        if ("true".equals(samlClient.forcePostBinding()))
          logoutBinding = SamlProtocol.SAML_POST_BINDING;
        String bindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
        UserSessionModel userSession = authResult.getSession();
        userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING_URI, bindingUri);
        if (samlClient.requiresRealmSignature()) {
          userSession.setNote(
              SamlProtocol.SAML_LOGOUT_SIGNATURE_ALGORITHM,
              samlClient.getSignatureAlgorithm().toString());
        }
        if (relayState != null)
          userSession.setNote(SamlProtocol.SAML_LOGOUT_RELAY_STATE, relayState);
        userSession.setNote(SamlProtocol.SAML_LOGOUT_REQUEST_ID, logoutRequest.getID());
        userSession.setNote(SamlProtocol.SAML_LOGOUT_BINDING, logoutBinding);
        userSession.setNote(
            SamlProtocol.SAML_LOGOUT_CANONICALIZATION, samlClient.getCanonicalizationMethod());
        userSession.setNote(
            AuthenticationManager.KEYCLOAK_LOGOUT_PROTOCOL, SamlProtocol.LOGIN_PROTOCOL);
        // remove client from logout requests
        for (ClientSessionModel clientSession : userSession.getClientSessions()) {
          if (clientSession.getClient().getId().equals(client.getId())) {
            clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
          }
        }
        logger.debug("browser Logout");
        return authManager.browserLogout(
            session, realm, userSession, uriInfo, clientConnection, headers);
      } else if (logoutRequest.getSessionIndex() != null) {
        for (String sessionIndex : logoutRequest.getSessionIndex()) {
          ClientSessionModel clientSession =
              session.sessions().getClientSession(realm, sessionIndex);
          if (clientSession == null) continue;
          UserSessionModel userSession = clientSession.getUserSession();
          if (clientSession.getClient().getClientId().equals(client.getClientId())) {
            // remove requesting client from logout
            clientSession.setAction(ClientSessionModel.Action.LOGGED_OUT.name());

            // Remove also other clientSessions of this client as there could be more in this
            // UserSession
            if (userSession != null) {
              for (ClientSessionModel clientSession2 : userSession.getClientSessions()) {
                if (clientSession2.getClient().getId().equals(client.getId())) {
                  clientSession2.setAction(ClientSessionModel.Action.LOGGED_OUT.name());
                }
              }
            }
          }

          try {
            authManager.backchannelLogout(
                session, realm, userSession, uriInfo, clientConnection, headers, true);
          } catch (Exception e) {
            logger.warn("Failure with backchannel logout", e);
          }
        }
      }

      // default

      String logoutBinding = getBindingType();
      String logoutBindingUri = SamlProtocol.getLogoutServiceUrl(uriInfo, client, logoutBinding);
      String logoutRelayState = relayState;
      SAML2LogoutResponseBuilder builder = new SAML2LogoutResponseBuilder();
      builder.logoutRequestID(logoutRequest.getID());
      builder.destination(logoutBindingUri);
      builder.issuer(RealmsResource.realmBaseUrl(uriInfo).build(realm.getName()).toString());
      JaxrsSAML2BindingBuilder binding =
          new JaxrsSAML2BindingBuilder().relayState(logoutRelayState);
      if (samlClient.requiresRealmSignature()) {
        SignatureAlgorithm algorithm = samlClient.getSignatureAlgorithm();
        KeyManager.ActiveKey keys = session.keys().getActiveKey(realm);
        binding
            .signatureAlgorithm(algorithm)
            .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
            .signDocument();
      }
      try {
        if (SamlProtocol.SAML_POST_BINDING.equals(logoutBinding)) {
          return binding.postBinding(builder.buildDocument()).response(logoutBindingUri);
        } else {
          return binding.redirectBinding(builder.buildDocument()).response(logoutBindingUri);
        }
      } catch (Exception e) {
        throw new RuntimeException(e);
      }
    }