/** * Create a new authentication flow * * @param flow Authentication flow representation * @return */ @Path("/flows") @POST @NoCache @Consumes(MediaType.APPLICATION_JSON) public Response createFlow(AuthenticationFlowRepresentation flow) { auth.requireManage(); if (flow.getAlias() == null || flow.getAlias().isEmpty()) { return ErrorResponse.exists("Failed to create flow with empty alias name"); } if (realm.getFlowByAlias(flow.getAlias()) != null) { return ErrorResponse.exists("Flow " + flow.getAlias() + " already exists"); } AuthenticationFlowModel createdModel = realm.addAuthenticationFlow(RepresentationToModel.toModel(flow)); flow.setId(createdModel.getId()); adminEvent .operation(OperationType.CREATE) .resourcePath(uriInfo, createdModel.getId()) .representation(flow) .success(); return Response.status(201).build(); }
/** * Set up a temporary password for the user * * <p>User will have to reset the temporary password next time they log in. * * @param id User id * @param pass A Temporary password */ @Path("{id}/reset-password") @PUT @Consumes(MediaType.APPLICATION_JSON) public void resetPassword(@PathParam("id") String id, CredentialRepresentation pass) { auth.requireManage(); UserModel user = session.users().getUserById(id, realm); if (user == null) { throw new NotFoundException("User not found"); } if (pass == null || pass.getValue() == null || !CredentialRepresentation.PASSWORD.equals(pass.getType())) { throw new BadRequestException("No password provided"); } UserCredentialModel cred = RepresentationToModel.convertCredential(pass); try { session.users().updateCredential(realm, user, cred); } catch (IllegalStateException ise) { throw new BadRequestException("Resetting to N old passwords is not allowed."); } catch (ModelReadOnlyException mre) { throw new BadRequestException("Can't reset password as account is read only"); } if (pass.isTemporary() != null && pass.isTemporary()) user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD); adminEvent.operation(OperationType.ACTION).resourcePath(uriInfo).success(); }
/** * 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()); if (Config.getAdminRealm().equals(realm.getName()) && (rep.getRealm() != null && !rep.getRealm().equals(Config.getAdminRealm()))) { return ErrorResponse.error("Can't rename master realm", Status.BAD_REQUEST); } try { if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getPrivateKey() != null && rep.getPublicKey() != null)) { try { KeyPairVerifier.verify(rep.getPrivateKey(), rep.getPublicKey()); } catch (VerificationException e) { return ErrorResponse.error(e.getMessage(), Status.BAD_REQUEST); } } if (!Constants.GENERATE.equals(rep.getPublicKey()) && (rep.getCertificate() != null)) { try { X509Certificate cert = PemUtils.decodeCertificate(rep.getCertificate()); if (cert == null) { return ErrorResponse.error("Failed to decode certificate", Status.BAD_REQUEST); } } catch (Exception e) { return ErrorResponse.error("Failed to decode certificate", Status.BAD_REQUEST); } } RepresentationToModel.updateRealm(rep, realm, session); // Refresh periodic sync tasks for configured federationProviders List<UserStorageProviderModel> federationProviders = realm.getUserStorageProviders(); UserStorageSyncManager usersSyncManager = new UserStorageSyncManager(); for (final UserStorageProviderModel fedProvider : federationProviders) { usersSyncManager.notifyToRefreshPeriodicSync(session, realm, fedProvider, false); } adminEvent .operation(OperationType.UPDATE) .representation(StripSecretsUtils.strip(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) { return ErrorResponse.exists("Realm with same name exists"); } catch (Exception e) { logger.error(e.getMessage(), e); return ErrorResponse.error("Failed to update realm", Response.Status.INTERNAL_SERVER_ERROR); } }
/** * Create new authenticator configuration * * @param rep JSON describing new authenticator configuration * @deprecated Use {@link #newExecutionConfig(String, AuthenticatorConfigRepresentation)} instead */ @Path("config") @POST @NoCache public Response createAuthenticatorConfig(AuthenticatorConfigRepresentation rep) { auth.requireManage(); AuthenticatorConfigModel config = realm.addAuthenticatorConfig(RepresentationToModel.toModel(rep)); adminEvent .operation(OperationType.CREATE) .resourcePath(uriInfo, config.getId()) .representation(rep) .success(); return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build(); }
/** * 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); } }
public void updateClientFromRep( ClientRepresentation rep, ClientModel client, KeycloakSession session) throws ModelDuplicateException { if (TRUE.equals(rep.isServiceAccountsEnabled()) && !client.isServiceAccountsEnabled()) { new ClientManager(new RealmManager(session)).enableServiceAccount(client); } if (!rep.getClientId().equals(client.getClientId())) { new ClientManager(new RealmManager(session)).clientIdChanged(client, rep.getClientId()); } RepresentationToModel.updateClient(rep, client); if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) { if (TRUE.equals(rep.getAuthorizationServicesEnabled())) { authorization().enable(); } else { authorization().disable(); } } }
/** * Update execution with new configuration * * @param execution Execution id * @param json JSON with new configuration * @return */ @Path("/executions/{executionId}/config") @POST @NoCache @Consumes(MediaType.APPLICATION_JSON) public Response newExecutionConfig( @PathParam("executionId") String execution, AuthenticatorConfigRepresentation json) { auth.requireManage(); AuthenticationExecutionModel model = realm.getAuthenticationExecutionById(execution); if (model == null) { session.getTransaction().setRollbackOnly(); throw new NotFoundException("Illegal execution"); } AuthenticatorConfigModel config = RepresentationToModel.toModel(json); config = realm.addAuthenticatorConfig(config); model.setAuthenticatorConfig(config.getId()); realm.updateAuthenticatorExecution(model); json.setId(config.getId()); adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(json).success(); return Response.created(uriInfo.getAbsolutePathBuilder().path(config.getId()).build()).build(); }
/** * Add new authentication execution * * @param execution JSON model describing authentication execution */ @Path("/executions") @POST @NoCache @Consumes(MediaType.APPLICATION_JSON) public Response addExecution(AuthenticationExecutionRepresentation execution) { auth.requireManage(); AuthenticationExecutionModel model = RepresentationToModel.toModel(realm, execution); AuthenticationFlowModel parentFlow = getParentFlow(model); if (parentFlow.isBuiltIn()) { throw new BadRequestException("It is illegal to add execution to a built in flow"); } model.setPriority(getNextPriority(parentFlow)); model = realm.addAuthenticatorExecution(model); adminEvent .operation(OperationType.CREATE) .resourcePath(uriInfo, model.getId()) .representation(execution) .success(); return Response.created(uriInfo.getAbsolutePathBuilder().path(model.getId()).build()).build(); }
/** * Should not be called from an import. This really expects that the client is created from the * admin console. * * @param session * @param realm * @param rep * @param addDefaultRoles * @return */ public static ClientModel createClient( KeycloakSession session, RealmModel realm, ClientRepresentation rep, boolean addDefaultRoles) { ClientModel client = RepresentationToModel.createClient(session, realm, rep, addDefaultRoles); if (rep.getProtocol() != null) { LoginProtocolFactory providerFactory = (LoginProtocolFactory) session .getKeycloakSessionFactory() .getProviderFactory(LoginProtocol.class, rep.getProtocol()); providerFactory.setupClientDefaults(rep, client); } // remove default mappers if there is a template if (rep.getProtocolMappers() == null && rep.getClientTemplate() != null) { Set<ProtocolMapperModel> mappers = client.getProtocolMappers(); for (ProtocolMapperModel mapper : mappers) client.removeProtocolMapper(mapper); } return client; }