Example #1
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());
    }
  }
    private ClientSessionCode parseClientSessionCode(String code) {
      ClientSessionCode clientCode = ClientSessionCode.parse(code, this.session, this.realm);

      if (clientCode != null
          && clientCode.isValid(AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) {
        ClientSessionModel clientSession = clientCode.getClientSession();

        if (clientSession != null) {
          ClientModel client = clientSession.getClient();

          if (client == null) {
            throw new IdentityBrokerException("Invalid client");
          }

          logger.debugf("Got authorization code from client [%s].", client.getClientId());
        }

        logger.debugf("Authorization code is valid.");

        return clientCode;
      }

      throw new IdentityBrokerException(
          "Invalid code, please login again through your application.");
    }
Example #3
0
 @Override
 public Response frontchannelLogout(
     UserSessionModel userSession, ClientSessionModel clientSession) {
   ClientModel client = clientSession.getClient();
   SamlClient samlClient = new SamlClient(client);
   if (!(client instanceof ClientModel)) return null;
   try {
     if (isLogoutPostBindingForClient(clientSession)) {
       String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
       SAML2LogoutRequestBuilder logoutBuilder =
           createLogoutRequest(bindingUri, clientSession, client);
       JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient);
       return binding.postBinding(logoutBuilder.buildDocument()).request(bindingUri);
     } else {
       logger.debug("frontchannel redirect binding");
       String bindingUri = getLogoutServiceUrl(uriInfo, client, SAML_REDIRECT_BINDING);
       SAML2LogoutRequestBuilder logoutBuilder =
           createLogoutRequest(bindingUri, clientSession, client);
       JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient);
       return binding.redirectBinding(logoutBuilder.buildDocument()).request(bindingUri);
     }
   } catch (ConfigurationException e) {
     throw new RuntimeException(e);
   } catch (ProcessingException e) {
     throw new RuntimeException(e);
   } catch (IOException e) {
     throw new RuntimeException(e);
   } catch (ParsingException e) {
     throw new RuntimeException(e);
   }
 }
Example #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;
  }
Example #5
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;
  }
Example #6
0
  protected boolean isLogoutPostBindingForClient(ClientSessionModel clientSession) {
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    String logoutPostUrl = client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_POST_ATTRIBUTE);
    String logoutRedirectUrl =
        client.getAttribute(SAML_SINGLE_LOGOUT_SERVICE_URL_REDIRECT_ATTRIBUTE);

    if (logoutPostUrl == null) {
      // if we don't have a redirect uri either, return true and default to the admin url + POST
      // binding
      if (logoutRedirectUrl == null) return true;
      return false;
    }

    if (samlClient.forcePostBinding()) {
      return true; // configured to force a post binding and post binding logout url is not null
    }

    String bindingType = clientSession.getNote(SAML_BINDING);

    // if the login binding was POST, return true
    if (SAML_POST_BINDING.equals(bindingType)) return true;

    if (logoutRedirectUrl == null)
      return true; // we don't have a redirect binding url, so use post binding

    return false; // redirect binding
  }
Example #7
0
  @Override
  public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    String logoutUrl = getLogoutServiceUrl(uriInfo, client, SAML_POST_BINDING);
    if (logoutUrl == null) {
      logger.warnv(
          "Can't do backchannel logout. No SingleLogoutService POST Binding registered for client: {1}",
          client.getClientId());
      return;
    }
    SAML2LogoutRequestBuilder logoutBuilder = createLogoutRequest(logoutUrl, clientSession, client);

    String logoutRequestString = null;
    try {
      JaxrsSAML2BindingBuilder binding = createBindingBuilder(samlClient);
      logoutRequestString = binding.postBinding(logoutBuilder.buildDocument()).encoded();
    } catch (Exception e) {
      logger.warn("failed to send saml logout", e);
      return;
    }

    HttpClient httpClient = session.getProvider(HttpClientProvider.class).getHttpClient();
    for (int i = 0; i < 2; i++) { // follow redirects once
      try {
        List<NameValuePair> formparams = new ArrayList<NameValuePair>();
        formparams.add(
            new BasicNameValuePair(GeneralConstants.SAML_REQUEST_KEY, logoutRequestString));
        formparams.add(
            new BasicNameValuePair("BACK_CHANNEL_LOGOUT", "BACK_CHANNEL_LOGOUT")); // for Picketlink
        // todo remove
        // this
        UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
        HttpPost post = new HttpPost(logoutUrl);
        post.setEntity(form);
        HttpResponse response = httpClient.execute(post);
        try {
          int status = response.getStatusLine().getStatusCode();
          if (status == 302 && !logoutUrl.endsWith("/")) {
            String redirect = response.getFirstHeader(HttpHeaders.LOCATION).getValue();
            String withSlash = logoutUrl + "/";
            if (withSlash.equals(redirect)) {
              logoutUrl = withSlash;
              continue;
            }
          }
        } finally {
          HttpEntity entity = response.getEntity();
          if (entity != null) {
            InputStream is = entity.getContent();
            if (is != null) is.close();
          }
        }
      } catch (IOException e) {
        logger.warn("failed to send saml logout", e);
      }
      break;
    }
  }
Example #8
0
 @Override
 public Response sendError(ClientSessionModel clientSession, Error error) {
   try {
     if ("true".equals(clientSession.getClient().getAttribute(SAML_IDP_INITIATED_LOGIN))) {
       if (error == Error.CANCELLED_BY_USER) {
         UriBuilder builder =
             RealmsResource.protocolUrl(uriInfo).path(SamlService.class, "idpInitiatedSSO");
         Map<String, String> params = new HashMap<>();
         params.put("realm", realm.getName());
         params.put("protocol", LOGIN_PROTOCOL);
         params.put(
             "client", clientSession.getClient().getAttribute(SAML_IDP_INITIATED_SSO_URL_NAME));
         URI redirect = builder.buildFromMap(params);
         return Response.status(302).location(redirect).build();
       } else {
         return ErrorPage.error(session, translateErrorToIdpInitiatedErrorMessage(error));
       }
     } else {
       SAML2ErrorResponseBuilder builder =
           new SAML2ErrorResponseBuilder()
               .destination(clientSession.getRedirectUri())
               .issuer(getResponseIssuer(realm))
               .status(translateErrorToSAMLStatus(error).get());
       try {
         JaxrsSAML2BindingBuilder binding =
             new JaxrsSAML2BindingBuilder()
                 .relayState(clientSession.getNote(GeneralConstants.RELAY_STATE));
         Document document = builder.buildDocument();
         return buildErrorResponse(clientSession, binding, document);
       } catch (Exception e) {
         return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
       }
     }
   } finally {
     RestartLoginCookie.expireRestartCookie(realm, session.getContext().getConnection(), uriInfo);
     session.sessions().removeClientSession(realm, clientSession);
   }
 }
Example #9
0
  @Override
  public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
    ClientSessionModel clientSession = accessCode.getClientSession();
    setupResponseTypeAndMode(clientSession);

    String redirect = clientSession.getRedirectUri();
    OIDCRedirectUriBuilder redirectUri = OIDCRedirectUriBuilder.fromUri(redirect, responseMode);
    String state = clientSession.getNote(OIDCLoginProtocol.STATE_PARAM);
    logger.debugv("redirectAccessCode: state: {0}", state);
    if (state != null) redirectUri.addParam(OAuth2Constants.STATE, state);

    // Standard or hybrid flow
    if (responseType.hasResponseType(OIDCResponseType.CODE)) {
      accessCode.setAction(ClientSessionModel.Action.CODE_TO_TOKEN.name());
      redirectUri.addParam(OAuth2Constants.CODE, accessCode.getCode());
    }

    // Implicit or hybrid flow
    if (responseType.isImplicitOrHybridFlow()) {
      TokenManager tokenManager = new TokenManager();
      AccessTokenResponse res =
          tokenManager
              .responseBuilder(
                  realm, clientSession.getClient(), event, session, userSession, clientSession)
              .generateAccessToken()
              .generateIDToken()
              .build();

      if (responseType.hasResponseType(OIDCResponseType.ID_TOKEN)) {
        redirectUri.addParam("id_token", res.getIdToken());
      }

      if (responseType.hasResponseType(OIDCResponseType.TOKEN)) {
        redirectUri.addParam("access_token", res.getToken());
        redirectUri.addParam("token_type", res.getTokenType());
        redirectUri.addParam("session-state", res.getSessionState());
        redirectUri.addParam("expires_in", String.valueOf(res.getExpiresIn()));
      }

      redirectUri.addParam("not-before-policy", String.valueOf(res.getNotBeforePolicy()));
    }

    return redirectUri.build();
  }
  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");
      }
    }
  }
Example #11
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;
  }
Example #12
0
  @Override
  public Response authenticated(UserSessionModel userSession, ClientSessionCode accessCode) {
    ClientSessionModel clientSession = accessCode.getClientSession();
    ClientModel client = clientSession.getClient();
    SamlClient samlClient = new SamlClient(client);
    String requestID = clientSession.getNote(SAML_REQUEST_ID);
    String relayState = clientSession.getNote(GeneralConstants.RELAY_STATE);
    String redirectUri = clientSession.getRedirectUri();
    String responseIssuer = getResponseIssuer(realm);
    String nameIdFormat = getNameIdFormat(samlClient, clientSession);
    String nameId = getNameId(nameIdFormat, clientSession, userSession);

    // save NAME_ID and format in clientSession as they may be persistent or transient or email and
    // not username
    // we'll need to send this back on a logout
    clientSession.setNote(SAML_NAME_ID, nameId);
    clientSession.setNote(SAML_NAME_ID_FORMAT, nameIdFormat);

    SAML2LoginResponseBuilder builder = new SAML2LoginResponseBuilder();
    builder
        .requestID(requestID)
        .destination(redirectUri)
        .issuer(responseIssuer)
        .assertionExpiration(realm.getAccessCodeLifespan())
        .subjectExpiration(realm.getAccessTokenLifespan())
        .sessionIndex(clientSession.getId())
        .requestIssuer(clientSession.getClient().getClientId())
        .nameIdentifier(nameIdFormat, nameId)
        .authMethod(JBossSAMLURIConstants.AC_UNSPECIFIED.get());
    if (!samlClient.includeAuthnStatement()) {
      builder.disableAuthnStatement(true);
    }

    List<ProtocolMapperProcessor<SAMLAttributeStatementMapper>> attributeStatementMappers =
        new LinkedList<>();
    List<ProtocolMapperProcessor<SAMLLoginResponseMapper>> loginResponseMappers =
        new LinkedList<>();
    ProtocolMapperProcessor<SAMLRoleListMapper> roleListMapper = null;

    Set<ProtocolMapperModel> mappings = accessCode.getRequestedProtocolMappers();
    for (ProtocolMapperModel mapping : mappings) {

      ProtocolMapper mapper =
          (ProtocolMapper)
              session
                  .getKeycloakSessionFactory()
                  .getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
      if (mapper == null) continue;
      if (mapper instanceof SAMLAttributeStatementMapper) {
        attributeStatementMappers.add(
            new ProtocolMapperProcessor<SAMLAttributeStatementMapper>(
                (SAMLAttributeStatementMapper) mapper, mapping));
      }
      if (mapper instanceof SAMLLoginResponseMapper) {
        loginResponseMappers.add(
            new ProtocolMapperProcessor<SAMLLoginResponseMapper>(
                (SAMLLoginResponseMapper) mapper, mapping));
      }
      if (mapper instanceof SAMLRoleListMapper) {
        roleListMapper =
            new ProtocolMapperProcessor<SAMLRoleListMapper>((SAMLRoleListMapper) mapper, mapping);
      }
    }

    Document samlDocument = null;
    try {
      ResponseType samlModel = builder.buildModel();
      final AttributeStatementType attributeStatement =
          populateAttributeStatements(
              attributeStatementMappers, session, userSession, clientSession);
      populateRoles(roleListMapper, session, userSession, clientSession, attributeStatement);

      // SAML Spec 2.7.3 AttributeStatement must contain one or more Attribute or EncryptedAttribute
      if (attributeStatement.getAttributes().size() > 0) {
        AssertionType assertion = samlModel.getAssertions().get(0).getAssertion();
        assertion.addStatement(attributeStatement);
      }

      samlModel =
          transformLoginResponse(
              loginResponseMappers, samlModel, session, userSession, clientSession);
      samlDocument = builder.buildDocument(samlModel);
    } catch (Exception e) {
      logger.error("failed", e);
      return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
    }

    JaxrsSAML2BindingBuilder bindingBuilder = new JaxrsSAML2BindingBuilder();
    bindingBuilder.relayState(relayState);

    KeyManager keyManager = session.keys();
    KeyManager.ActiveKey keys = keyManager.getActiveKey(realm);

    if (samlClient.requiresRealmSignature()) {
      String canonicalization = samlClient.getCanonicalizationMethod();
      if (canonicalization != null) {
        bindingBuilder.canonicalizationMethod(canonicalization);
      }
      bindingBuilder
          .signatureAlgorithm(samlClient.getSignatureAlgorithm())
          .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
          .signDocument();
    }
    if (samlClient.requiresAssertionSignature()) {
      String canonicalization = samlClient.getCanonicalizationMethod();
      if (canonicalization != null) {
        bindingBuilder.canonicalizationMethod(canonicalization);
      }
      bindingBuilder
          .signatureAlgorithm(samlClient.getSignatureAlgorithm())
          .signWith(keys.getPrivateKey(), keys.getPublicKey(), keys.getCertificate())
          .signAssertions();
    }
    if (samlClient.requiresEncryption()) {
      PublicKey publicKey = null;
      try {
        publicKey = SamlProtocolUtils.getEncryptionValidationKey(client);
      } catch (Exception e) {
        logger.error("failed", e);
        return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
      }
      bindingBuilder.encrypt(publicKey);
    }
    try {
      return buildAuthenticatedResponse(clientSession, redirectUri, samlDocument, bindingBuilder);
    } catch (Exception e) {
      logger.error("failed", e);
      return ErrorPage.error(session, Messages.FAILED_TO_PROCESS_RESPONSE);
    }
  }
  /**
   * 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);
  }
Example #14
0
 @Override
 public void backchannelLogout(UserSessionModel userSession, ClientSessionModel clientSession) {
   ClientModel client = clientSession.getClient();
   new ResourceAdminManager(session)
       .logoutClientSession(uriInfo.getRequestUri(), realm, client, clientSession);
 }
Example #15
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);
  }
Example #16
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);
  }
Example #17
0
 protected boolean isPostBinding(ClientSessionModel clientSession) {
   ClientModel client = clientSession.getClient();
   SamlClient samlClient = new SamlClient(client);
   return SamlProtocol.SAML_POST_BINDING.equals(clientSession.getNote(SamlProtocol.SAML_BINDING))
       || samlClient.forcePostBinding();
 }
Example #18
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);
      }
    }
 public boolean verifyCode(String code) {
   if (!checkSsl()) {
     event.error(Errors.SSL_REQUIRED);
     response = ErrorPage.error(session, Messages.HTTPS_REQUIRED);
     return false;
   }
   if (!realm.isEnabled()) {
     event.error(Errors.REALM_DISABLED);
     response = ErrorPage.error(session, Messages.REALM_NOT_ENABLED);
     return false;
   }
   ClientSessionCode.ParseResult result = ClientSessionCode.parseResult(code, session, realm);
   clientCode = result.getCode();
   if (clientCode == null) {
     if (result.isClientSessionNotFound()) { // timeout
       try {
         ClientSessionModel clientSession =
             RestartLoginCookie.restartSession(session, realm, code);
         if (clientSession != null) {
           event
               .clone()
               .detail(Details.RESTART_AFTER_TIMEOUT, "true")
               .error(Errors.EXPIRED_CODE);
           response =
               processFlow(
                   null,
                   clientSession,
                   AUTHENTICATE_PATH,
                   realm.getBrowserFlow(),
                   Messages.LOGIN_TIMEOUT);
           return false;
         }
       } catch (Exception e) {
         logger.error("failed to parse RestartLoginCookie", e);
       }
     }
     event.error(Errors.INVALID_CODE);
     response = ErrorPage.error(session, Messages.INVALID_CODE);
     return false;
   }
   ClientSessionModel clientSession = clientCode.getClientSession();
   if (clientSession == null) {
     event.error(Errors.INVALID_CODE);
     response = ErrorPage.error(session, Messages.INVALID_CODE);
     return false;
   }
   event.detail(Details.CODE_ID, clientSession.getId());
   ClientModel client = clientSession.getClient();
   if (client == null) {
     event.error(Errors.CLIENT_NOT_FOUND);
     response = ErrorPage.error(session, Messages.UNKNOWN_LOGIN_REQUESTER);
     session.sessions().removeClientSession(realm, clientSession);
     return false;
   }
   if (!client.isEnabled()) {
     event.error(Errors.CLIENT_NOT_FOUND);
     response = ErrorPage.error(session, Messages.LOGIN_REQUESTER_NOT_ENABLED);
     session.sessions().removeClientSession(realm, clientSession);
     return false;
   }
   session.getContext().setClient(client);
   return true;
 }