Esempio n. 1
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);
    }
  }
Esempio n. 2
0
  /**
   * Get represenation of the user
   *
   * @param id User id
   * @return
   */
  @Path("{id}")
  @GET
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public UserRepresentation getUser(final @PathParam("id") String id) {
    auth.requireView();

    UserModel user = session.users().getUserById(id, realm);
    if (user == null) {
      throw new NotFoundException("User not found");
    }

    UserRepresentation rep = ModelToRepresentation.toRepresentation(user);

    if (realm.isIdentityFederationEnabled()) {
      List<FederatedIdentityRepresentation> reps = getFederatedIdentities(user);
      rep.setFederatedIdentities(reps);
    }

    if (session
        .getProvider(BruteForceProtector.class)
        .isTemporarilyDisabled(session, realm, rep.getUsername())) {
      rep.setEnabled(false);
    }

    return rep;
  }
  /**
   * Get status of a username in brute force detection
   *
   * @param username
   * @return
   */
  @GET
  @Path("brute-force/usernames/{username}")
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public Map<String, Object> bruteForceUserStatus(@PathParam("username") String username) {
    auth.requireView();

    Map<String, Object> data = new HashMap<>();
    data.put("disabled", false);
    data.put("numFailures", 0);
    data.put("lastFailure", 0);
    data.put("lastIPFailure", "n/a");
    if (!realm.isBruteForceProtected()) return data;

    UsernameLoginFailureModel model =
        session.sessions().getUserLoginFailure(realm, username.toLowerCase());
    if (model == null) return data;
    if (session
        .getProvider(BruteForceProtector.class)
        .isTemporarilyDisabled(session, realm, username)) {
      data.put("disabled", true);
    }
    data.put("numFailures", model.getNumFailures());
    data.put("lastFailure", model.getLastFailure());
    data.put("lastIPFailure", model.getLastIPFailure());
    return data;
  }
Esempio n. 4
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;
    }
  }
Esempio n. 5
0
  /** Delete all admin events */
  @Path("admin-events")
  @DELETE
  public void clearAdminEvents() {
    auth.init(RealmAuth.Resource.EVENTS).requireManage();

    EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
    eventStore.clearAdmin(realm.getId());
  }
 protected <T> List<T> getCredentialProviders(RealmModel realm, Class<T> type) {
   List<T> list = new LinkedList<T>();
   for (ProviderFactory f :
       session.getKeycloakSessionFactory().getProviderFactories(CredentialProvider.class)) {
     if (!Types.supports(CredentialInputUpdater.class, f, CredentialProviderFactory.class))
       continue;
     list.add((T) session.getProvider(CredentialProvider.class, f.getId()));
   }
   return list;
 }
  /** Clear cache of external public keys (Public keys of clients or Identity providers) */
  @Path("clear-keys-cache")
  @POST
  public void clearKeysCache() {
    auth.requireManage();

    PublicKeyStorageProvider cache = session.getProvider(PublicKeyStorageProvider.class);
    if (cache != null) {
      cache.clearCache();
    }

    adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
  }
Esempio n. 8
0
  /** Clear user cache */
  @Path("clear-user-cache")
  @POST
  public void clearUserCache() {
    auth.requireManage();

    CacheUserProvider cache = session.getProvider(CacheUserProvider.class);
    if (cache != null) {
      cache.clear();
    }

    adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success();
  }
  @Override
  public UserSessionProvider create(KeycloakSession session) {
    InfinispanConnectionProvider connections =
        session.getProvider(InfinispanConnectionProvider.class);
    Cache<String, SessionEntity> cache =
        connections.getCache(InfinispanConnectionProvider.SESSION_CACHE_NAME);
    Cache<String, SessionEntity> offlineSessionsCache =
        connections.getCache(InfinispanConnectionProvider.OFFLINE_SESSION_CACHE_NAME);
    Cache<LoginFailureKey, LoginFailureEntity> loginFailures =
        connections.getCache(InfinispanConnectionProvider.LOGIN_FAILURE_CACHE_NAME);

    return new InfinispanUserSessionProvider(session, cache, offlineSessionsCache, loginFailures);
  }
Esempio n. 10
0
  @GET
  @NoCache
  @Path("installation/providers/{providerId}")
  public Response getInstallationProvider(@PathParam("providerId") String providerId) {
    auth.requireView();

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

    ClientInstallationProvider provider =
        session.getProvider(ClientInstallationProvider.class, providerId);
    if (provider == null) throw new NotFoundException("Unknown Provider");
    return provider.generateInstallation(session, realm, client, keycloak.getBaseUri(uriInfo));
  }
  @Override
  public void postInit(KeycloakSessionFactory factory) {
    factory.register(
        event -> {
          if (event instanceof ClientRemovedEvent) {
            KeycloakSession keycloakSession = ((ClientRemovedEvent) event).getKeycloakSession();
            AuthorizationProvider provider =
                keycloakSession.getProvider(AuthorizationProvider.class);
            PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
            ClientModel removedClient = ((ClientRemovedEvent) event).getClient();

            policyStore
                .findByType(getId())
                .forEach(
                    policy -> {
                      List<String> clients = new ArrayList<>();

                      for (String clientId : getClients(policy)) {
                        if (!clientId.equals(removedClient.getId())) {
                          clients.add(clientId);
                        }
                      }

                      try {
                        if (clients.isEmpty()) {
                          policyStore
                              .findDependentPolicies(policy.getId())
                              .forEach(
                                  dependentPolicy -> {
                                    dependentPolicy.removeAssociatedPolicy(policy);
                                  });
                          policyStore.delete(policy.getId());
                        } else {
                          policy
                              .getConfig()
                              .put("clients", JsonSerialization.writeValueAsString(clients));
                        }
                      } catch (IOException e) {
                        throw new RuntimeException(
                            "Error while synchronizing clients with policy ["
                                + policy.getName()
                                + "].",
                            e);
                      }
                    });
          }
        });
  }
Esempio n. 12
0
  /**
   * Update the top-level information of the realm
   *
   * <p>Any user, roles or client information in the representation will be ignored. This will only
   * update top-level attributes of the realm.
   *
   * @param rep
   * @return
   */
  @PUT
  @Consumes(MediaType.APPLICATION_JSON)
  public Response updateRealm(final RealmRepresentation rep) {
    auth.requireManage();

    logger.debug("updating realm: " + realm.getName());
    try {
      RepresentationToModel.updateRealm(rep, realm);
      if (rep.isRealmCacheEnabled() != null && session.realms() instanceof CacheRealmProvider) {
        CacheRealmProvider cacheRealmProvider = (CacheRealmProvider) session.realms();
        cacheRealmProvider.setEnabled(rep.isRealmCacheEnabled());
      }
      if (rep.isUserCacheEnabled() != null && session.userStorage() instanceof CacheUserProvider) {
        CacheUserProvider cache = (CacheUserProvider) session.userStorage();
        cache.setEnabled(rep.isUserCacheEnabled());
      }

      // Refresh periodic sync tasks for configured federationProviders
      List<UserFederationProviderModel> federationProviders = realm.getUserFederationProviders();
      UsersSyncManager usersSyncManager = new UsersSyncManager();
      for (final UserFederationProviderModel fedProvider : federationProviders) {
        usersSyncManager.refreshPeriodicSyncForProvider(
            session.getKeycloakSessionFactory(),
            session.getProvider(TimerProvider.class),
            fedProvider,
            realm.getId());
      }

      adminEvent.operation(OperationType.UPDATE).representation(rep).success();
      return Response.noContent().build();
    } catch (PatternSyntaxException e) {
      return ErrorResponse.error(
          "Specified regex pattern(s) is invalid.", Response.Status.BAD_REQUEST);
    } catch (ModelDuplicateException e) {
      throw e;
    } catch (Exception e) {
      logger.error(e);
      return ErrorResponse.error(
          "Failed to update " + rep.getRealm() + " Realm.", Response.Status.INTERNAL_SERVER_ERROR);
    }
  }
Esempio n. 13
0
  private void addDefaultMappers(KeycloakSession session, DBCollection clients) {
    DBCursor clientsCursor = clients.find();
    try {
      while (clientsCursor.hasNext()) {
        BasicDBObject currentClient = (BasicDBObject) clientsCursor.next();

        BasicDBList dbProtocolMappers = new BasicDBList();
        currentClient.put("protocolMappers", dbProtocolMappers);

        Object claimMask = currentClient.get("allowedClaimsMask");
        MigrationProvider migrationProvider = session.getProvider(MigrationProvider.class);
        List<ProtocolMapperRepresentation> protocolMappers =
            migrationProvider.getMappersForClaimMask((Long) claimMask);

        for (ProtocolMapperRepresentation protocolMapper : protocolMappers) {
          BasicDBObject dbMapper = new BasicDBObject();
          dbMapper.put("id", KeycloakModelUtils.generateId());
          dbMapper.put("protocol", protocolMapper.getProtocol());
          dbMapper.put("name", protocolMapper.getName());
          dbMapper.put("consentRequired", protocolMapper.isConsentRequired());
          dbMapper.put("consentText", protocolMapper.getConsentText());
          dbMapper.put("protocolMapper", protocolMapper.getProtocolMapper());

          Map<String, String> config = protocolMapper.getConfig();
          BasicDBObject dbConfig = MapMapper.convertMap(config);
          dbMapper.put("config", dbConfig);

          dbProtocolMappers.add(dbMapper);
        }

        // Remove obsolete keys from client
        currentClient.remove("allowedClaimsMask");

        log.debugv("Added default mappers to application {1}", currentClient.get("name"));
        clients.save(currentClient);
      }
    } finally {
      clientsCursor.close();
    }
  }
 @Override
 public RealmProvider create(KeycloakSession session) {
   MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
   return new MongoRealmProvider(session, connection.getInvocationContext());
 }
Esempio n. 15
0
  /**
   * Get admin events
   *
   * <p>Returns all admin events, or filters events based on URL query parameters listed here
   *
   * @param operationTypes
   * @param authRealm
   * @param authClient
   * @param authUser user id
   * @param authIpAddress
   * @param resourcePath
   * @param dateTo
   * @param dateFrom
   * @param firstResult
   * @param maxResults
   * @return
   */
  @Path("admin-events")
  @GET
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public List<AdminEventRepresentation> getEvents(
      @QueryParam("operationTypes") List<String> operationTypes,
      @QueryParam("authRealm") String authRealm,
      @QueryParam("authClient") String authClient,
      @QueryParam("authUser") String authUser,
      @QueryParam("authIpAddress") String authIpAddress,
      @QueryParam("resourcePath") String resourcePath,
      @QueryParam("dateFrom") String dateFrom,
      @QueryParam("dateTo") String dateTo,
      @QueryParam("first") Integer firstResult,
      @QueryParam("max") Integer maxResults,
      @QueryParam("resourceTypes") List<String> resourceTypes) {
    auth.init(RealmAuth.Resource.EVENTS).requireView();

    EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);
    AdminEventQuery query = eventStore.createAdminQuery().realm(realm.getId());
    ;

    if (authRealm != null) {
      query.authRealm(authRealm);
    }

    if (authClient != null) {
      query.authClient(authClient);
    }

    if (authUser != null) {
      query.authUser(authUser);
    }

    if (authIpAddress != null) {
      query.authIpAddress(authIpAddress);
    }

    if (resourcePath != null) {
      query.resourcePath(resourcePath);
    }

    if (operationTypes != null && !operationTypes.isEmpty()) {
      OperationType[] t = new OperationType[operationTypes.size()];
      for (int i = 0; i < t.length; i++) {
        t[i] = OperationType.valueOf(operationTypes.get(i));
      }
      query.operation(t);
    }

    if (resourceTypes != null && !resourceTypes.isEmpty()) {
      ResourceType[] t = new ResourceType[resourceTypes.size()];
      for (int i = 0; i < t.length; i++) {
        t[i] = ResourceType.valueOf(resourceTypes.get(i));
      }
      query.resourceType(t);
    }

    if (dateFrom != null) {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      Date from = null;
      try {
        from = df.parse(dateFrom);
      } catch (ParseException e) {
        throw new BadRequestException(
            "Invalid value for 'Date(From)', expected format is yyyy-MM-dd");
      }
      query.fromTime(from);
    }

    if (dateTo != null) {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      Date to = null;
      try {
        to = df.parse(dateTo);
      } catch (ParseException e) {
        throw new BadRequestException(
            "Invalid value for 'Date(To)', expected format is yyyy-MM-dd");
      }
      query.toTime(to);
    }

    if (firstResult != null) {
      query.firstResult(firstResult);
    }
    if (maxResults != null) {
      query.maxResults(maxResults);
    }

    return toAdminEventRep(query.getResultList());
  }
Esempio n. 16
0
  /**
   * Get events
   *
   * <p>Returns all events, or filters them based on URL query parameters listed here
   *
   * @param types The types of events to return
   * @param client App or oauth client name
   * @param user User id
   * @param ipAddress IP address
   * @param dateTo To date
   * @param dateFrom From date
   * @param firstResult Paging offset
   * @param maxResults Paging size
   * @return
   */
  @Path("events")
  @GET
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public List<EventRepresentation> getEvents(
      @QueryParam("type") List<String> types,
      @QueryParam("client") String client,
      @QueryParam("user") String user,
      @QueryParam("dateFrom") String dateFrom,
      @QueryParam("dateTo") String dateTo,
      @QueryParam("ipAddress") String ipAddress,
      @QueryParam("first") Integer firstResult,
      @QueryParam("max") Integer maxResults) {
    auth.init(RealmAuth.Resource.EVENTS).requireView();

    EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class);

    EventQuery query = eventStore.createQuery().realm(realm.getId());
    if (client != null) {
      query.client(client);
    }

    if (types != null & !types.isEmpty()) {
      EventType[] t = new EventType[types.size()];
      for (int i = 0; i < t.length; i++) {
        t[i] = EventType.valueOf(types.get(i));
      }
      query.type(t);
    }

    if (user != null) {
      query.user(user);
    }

    if (dateFrom != null) {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      Date from = null;
      try {
        from = df.parse(dateFrom);
      } catch (ParseException e) {
        throw new BadRequestException(
            "Invalid value for 'Date(From)', expected format is yyyy-MM-dd");
      }
      query.fromDate(from);
    }

    if (dateTo != null) {
      SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
      Date to = null;
      try {
        to = df.parse(dateTo);
      } catch (ParseException e) {
        throw new BadRequestException(
            "Invalid value for 'Date(To)', expected format is yyyy-MM-dd");
      }
      query.toDate(to);
    }

    if (ipAddress != null) {
      query.ipAddress(ipAddress);
    }
    if (firstResult != null) {
      query.firstResult(firstResult);
    }
    if (maxResults != null) {
      query.maxResults(maxResults);
    }

    return toEventListRep(query.getResultList());
  }
 @Override
 public StoreFactory create(KeycloakSession session) {
   MongoConnectionProvider connection = session.getProvider(MongoConnectionProvider.class);
   return new MongoStoreFactory(connection.getInvocationContext(), session);
 }
Esempio n. 18
0
 @Override
 public UserProvider getDelegate() {
   if (delegate != null) return delegate;
   delegate = session.getProvider(UserProvider.class);
   return delegate;
 }
 private void resetSession() {
   kc.stopSession(session, true);
   session = kc.startSession();
   eventStore = session.getProvider(EventStoreProvider.class);
 }
 public TestCacheResource(KeycloakSession session, String cacheName) {
   InfinispanConnectionProvider provider = session.getProvider(InfinispanConnectionProvider.class);
   cache = provider.getCache(cacheName);
 }
 @Before
 public void before() {
   session = kc.startSession();
   eventStore = session.getProvider(EventStoreProvider.class);
 }
Esempio n. 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);
  }