@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); } }
/** * 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; }
@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; } }
/** 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(); }
/** 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); }
@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); } }); } }); }
/** * 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); } }
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()); }
/** * 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()); }
/** * 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); }
@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); }
/** * 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); }