/**
   * Get unregistered required actions
   *
   * <p>Returns a list of unregistered required actions.
   */
  @Path("unregistered-required-actions")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @NoCache
  public List<Map<String, String>> getUnregisteredRequiredActions() {
    auth.requireView();

    List<ProviderFactory> factories =
        session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class);
    List<Map<String, String>> unregisteredList = new LinkedList<>();
    for (ProviderFactory factory : factories) {
      RequiredActionFactory requiredActionFactory = (RequiredActionFactory) factory;
      boolean found = false;
      for (RequiredActionProviderModel model : realm.getRequiredActionProviders()) {
        if (model.getProviderId().equals(factory.getId())) {
          found = true;
          break;
        }
      }
      if (!found) {
        Map<String, String> data = new HashMap<>();
        data.put("name", requiredActionFactory.getDisplayText());
        data.put("providerId", requiredActionFactory.getId());
        unregisteredList.add(data);
      }
    }
    return unregisteredList;
  }
  /** Get configuration descriptions for all clients */
  @Path("per-client-config-description")
  @GET
  @Produces(MediaType.APPLICATION_JSON)
  @NoCache
  public Map<String, List<ConfigPropertyRepresentation>> getPerClientConfigDescription() {
    auth.requireAny();

    List<ProviderFactory> factories =
        session.getKeycloakSessionFactory().getProviderFactories(ClientAuthenticator.class);

    Map<String, List<ConfigPropertyRepresentation>> toReturn = new HashMap<>();
    for (ProviderFactory clientAuthenticatorFactory : factories) {
      String providerId = clientAuthenticatorFactory.getId();
      ConfigurableAuthenticatorFactory factory =
          CredentialHelper.getConfigurableAuthenticatorFactory(session, providerId);
      ClientAuthenticatorFactory clientAuthFactory = (ClientAuthenticatorFactory) factory;
      List<ProviderConfigProperty> perClientConfigProps =
          clientAuthFactory.getConfigPropertiesPerClient();
      List<ConfigPropertyRepresentation> result = new LinkedList<>();
      for (ProviderConfigProperty prop : perClientConfigProps) {
        ConfigPropertyRepresentation propRep = getConfigPropertyRep(prop);
        result.add(propRep);
      }

      toReturn.put(providerId, result);
    }

    return toReturn;
  }
 @Override
 public List<ProtocolMapperModel> getBuiltinMappers(String protocol) {
   LoginProtocolFactory providerFactory =
       (LoginProtocolFactory)
           session.getKeycloakSessionFactory().getProviderFactory(LoginProtocol.class, protocol);
   return providerFactory.getBuiltinMappers();
 }
예제 #4
0
 public static LDAPFederationProvider getLdapProvider(
     KeycloakSession keycloakSession, UserFederationProviderModel ldapFedModel) {
   LDAPFederationProviderFactory ldapProviderFactory =
       (LDAPFederationProviderFactory)
           keycloakSession
               .getKeycloakSessionFactory()
               .getProviderFactory(UserFederationProvider.class, ldapFedModel.getProviderName());
   return ldapProviderFactory.getInstance(keycloakSession, ldapFedModel);
 }
  /**
   * Add new authentication execution to a flow
   *
   * @param flowAlias Alias of parent flow
   * @param data New execution JSON data containing 'provider' attribute
   */
  @Path("/flows/{flowAlias}/executions/execution")
  @POST
  @NoCache
  @Consumes(MediaType.APPLICATION_JSON)
  public void addExecution(@PathParam("flowAlias") String flowAlias, Map<String, String> data) {
    auth.requireManage();

    AuthenticationFlowModel parentFlow = realm.getFlowByAlias(flowAlias);
    if (parentFlow == null) {
      throw new BadRequestException("Parent flow doesn't exists");
    }
    if (parentFlow.isBuiltIn()) {
      throw new BadRequestException("It is illegal to add execution to a built in flow");
    }
    String provider = data.get("provider");

    // make sure provider is one of the registered providers
    ProviderFactory f;
    if (parentFlow.getProviderId().equals(AuthenticationFlow.CLIENT_FLOW)) {
      f =
          session
              .getKeycloakSessionFactory()
              .getProviderFactory(ClientAuthenticator.class, provider);
    } else if (parentFlow.getProviderId().equals(AuthenticationFlow.FORM_FLOW)) {
      f = session.getKeycloakSessionFactory().getProviderFactory(FormAction.class, provider);
    } else {
      f = session.getKeycloakSessionFactory().getProviderFactory(Authenticator.class, provider);
    }
    if (f == null) {
      throw new BadRequestException("No authentication provider found for id: " + provider);
    }

    AuthenticationExecutionModel execution = new AuthenticationExecutionModel();
    execution.setParentFlow(parentFlow.getId());
    execution.setRequirement(AuthenticationExecutionModel.Requirement.DISABLED);
    execution.setAuthenticatorFlow(false);
    execution.setAuthenticator(provider);
    execution.setPriority(getNextPriority(parentFlow));

    execution = realm.addAuthenticatorExecution(execution);

    data.put("id", execution.getId());
    adminEvent.operation(OperationType.CREATE).resourcePath(uriInfo).representation(data).success();
  }
 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;
 }
  /**
   * Get form providers
   *
   * <p>Returns a list of form providers.
   */
  @Path("/form-providers")
  @GET
  @NoCache
  @Produces(MediaType.APPLICATION_JSON)
  public List<Map<String, Object>> getFormProviders() {
    auth.requireView();

    List<ProviderFactory> factories =
        session.getKeycloakSessionFactory().getProviderFactories(FormAuthenticator.class);
    return buildProviderMetadata(factories);
  }
예제 #8
0
  /**
   * Base path for importing clients under this realm.
   *
   * @return
   */
  @Path("client-description-converter")
  @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  public ClientRepresentation convertClientDescription(String description) {
    for (ProviderFactory<ClientDescriptionConverter> factory :
        session
            .getKeycloakSessionFactory()
            .getProviderFactories(ClientDescriptionConverter.class)) {
      if (((ClientDescriptionConverterFactory) factory).isSupported(description)) {
        return factory.create(session).convertToInternal(description);
      }
    }

    throw new BadRequestException("Unsupported format");
  }
예제 #9
0
  public static void updateUserFromRep(
      UserModel user,
      UserRepresentation rep,
      Set<String> attrsToRemove,
      RealmModel realm,
      KeycloakSession session) {
    if (realm.isEditUsernameAllowed()) {
      user.setUsername(rep.getUsername());
    }
    user.setEmail(rep.getEmail());
    user.setFirstName(rep.getFirstName());
    user.setLastName(rep.getLastName());

    if (rep.isEnabled() != null) user.setEnabled(rep.isEnabled());
    if (rep.isTotp() != null) user.setOtpEnabled(rep.isTotp());
    if (rep.isEmailVerified() != null) user.setEmailVerified(rep.isEmailVerified());

    List<String> reqActions = rep.getRequiredActions();

    if (reqActions != null) {
      Set<String> allActions = new HashSet<>();
      for (ProviderFactory factory :
          session.getKeycloakSessionFactory().getProviderFactories(RequiredActionProvider.class)) {
        allActions.add(factory.getId());
      }
      for (String action : allActions) {
        if (reqActions.contains(action)) {
          user.addRequiredAction(action);
        } else {
          user.removeRequiredAction(action);
        }
      }
    }

    if (rep.getAttributesAsListValues() != null) {
      for (Map.Entry<String, List<String>> attr : rep.getAttributesAsListValues().entrySet()) {
        user.setAttribute(attr.getKey(), attr.getValue());
      }

      for (String attr : attrsToRemove) {
        user.removeAttribute(attr);
      }
    }
  }
  private static Map<String, ProtocolMapperRepresentation> getAllDefaultMappers(
      KeycloakSession session) {
    Map<String, ProtocolMapperRepresentation> allMappers =
        new HashMap<String, ProtocolMapperRepresentation>();

    List<ProviderFactory> loginProtocolFactories =
        session.getKeycloakSessionFactory().getProviderFactories(LoginProtocol.class);

    for (ProviderFactory factory : loginProtocolFactories) {
      LoginProtocolFactory loginProtocolFactory = (LoginProtocolFactory) factory;
      List<ProtocolMapperModel> currentMappers = loginProtocolFactory.getDefaultBuiltinMappers();

      for (ProtocolMapperModel protocolMapper : currentMappers) {
        ProtocolMapperRepresentation rep = ModelToRepresentation.toRepresentation(protocolMapper);
        allMappers.put(protocolMapper.getName(), rep);
      }
    }

    return allMappers;
  }
예제 #11
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);
    }
  }
예제 #12
0
  public void transformIDToken(
      KeycloakSession session,
      IDToken token,
      RealmModel realm,
      ClientModel client,
      UserModel user,
      UserSessionModel userSession,
      ClientSessionModel clientSession) {
    Set<ProtocolMapperModel> mappings =
        new ClientSessionCode(realm, clientSession).getRequestedProtocolMappers();
    KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
    for (ProtocolMapperModel mapping : mappings) {

      ProtocolMapper mapper =
          (ProtocolMapper)
              sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
      if (mapper == null || !(mapper instanceof OIDCIDTokenMapper)) continue;
      token =
          ((OIDCIDTokenMapper) mapper)
              .transformIDToken(token, mapping, session, userSession, clientSession);
    }
  }
예제 #13
0
  /**
   * Base path for importing clients under this realm.
   *
   * @return
   */
  @Path("client-description-converter")
  @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN})
  @POST
  @Produces(MediaType.APPLICATION_JSON)
  public ClientRepresentation convertClientDescription(String description) {
    auth.init(Resource.CLIENT).requireManage();

    if (realm == null) {
      throw new NotFoundException("Realm not found.");
    }

    for (ProviderFactory<ClientDescriptionConverter> factory :
        session
            .getKeycloakSessionFactory()
            .getProviderFactories(ClientDescriptionConverter.class)) {
      if (((ClientDescriptionConverterFactory) factory).isSupported(description)) {
        return factory.create(session).convertToInternal(description);
      }
    }

    throw new BadRequestException("Unsupported format");
  }
예제 #14
0
  /**
   * 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;
  }
예제 #15
0
  public Response processRequireAction(final String code, String action) {
    event.event(EventType.CUSTOM_REQUIRED_ACTION);
    event.detail(Details.CUSTOM_REQUIRED_ACTION, action);
    if (action == null) {
      logger.error("required action query param was null");
      event.error(Errors.INVALID_CODE);
      throw new WebApplicationException(ErrorPage.error(session, Messages.INVALID_CODE));
    }

    RequiredActionFactory factory =
        (RequiredActionFactory)
            session
                .getKeycloakSessionFactory()
                .getProviderFactory(RequiredActionProvider.class, action);
    if (factory == null) {
      logger.error("required action provider was null");
      event.error(Errors.INVALID_CODE);
      throw new WebApplicationException(ErrorPage.error(session, Messages.INVALID_CODE));
    }
    RequiredActionProvider provider = factory.create(session);
    Checks checks = new Checks();
    if (!checks.verifyCode(code, action)) {
      return checks.response;
    }
    final ClientSessionCode clientCode = checks.clientCode;
    final ClientSessionModel clientSession = clientCode.getClientSession();

    if (clientSession.getUserSession() == null) {
      logger.error("user session was null");
      event.error(Errors.USER_SESSION_NOT_FOUND);
      throw new WebApplicationException(ErrorPage.error(session, Messages.SESSION_NOT_ACTIVE));
    }

    initEvent(clientSession);
    event.event(EventType.CUSTOM_REQUIRED_ACTION);

    RequiredActionContextResult context =
        new RequiredActionContextResult(
            clientSession.getUserSession(),
            clientSession,
            realm,
            event,
            session,
            request,
            clientSession.getUserSession().getUser(),
            factory) {
          @Override
          public String generateAccessCode(String action) {
            String clientSessionAction = clientSession.getAction();
            if (action.equals(clientSessionAction)) {
              clientSession.setTimestamp(Time.currentTime());
              return code;
            }
            ClientSessionCode code = new ClientSessionCode(getRealm(), getClientSession());
            code.setAction(action);
            return code.getCode();
          }

          @Override
          public void ignore() {
            throw new RuntimeException("Cannot call ignore within processAction()");
          }
        };
    provider.processAction(context);
    if (context.getStatus() == RequiredActionContext.Status.SUCCESS) {
      event.clone().success();
      // do both
      clientSession.removeRequiredAction(factory.getId());
      clientSession.getUserSession().getUser().removeRequiredAction(factory.getId());
      event.event(EventType.LOGIN);
      return AuthenticationManager.nextActionAfterAuthentication(
          session,
          clientSession.getUserSession(),
          clientSession,
          clientConnection,
          request,
          uriInfo,
          event);
    }
    if (context.getStatus() == RequiredActionContext.Status.CHALLENGE) {
      return context.getChallenge();
    }
    if (context.getStatus() == RequiredActionContext.Status.FAILURE) {
      LoginProtocol protocol =
          context
              .getSession()
              .getProvider(LoginProtocol.class, context.getClientSession().getAuthMethod());
      protocol
          .setRealm(context.getRealm())
          .setHttpHeaders(context.getHttpRequest().getHttpHeaders())
          .setUriInfo(context.getUriInfo());
      event.detail(Details.CUSTOM_REQUIRED_ACTION, action).error(Errors.REJECTED_BY_USER);
      return protocol.consentDenied(context.getClientSession());
    }

    throw new RuntimeException("Unreachable");
  }
예제 #16
0
  // Moved to static method, so it's possible to test this from other places too (for example
  // export-import tests)
  public static void assertDataImportedInRealm(KeycloakSession session, RealmModel realm) {
    Assert.assertTrue(realm.isVerifyEmail());

    List<RequiredCredentialModel> creds = realm.getRequiredCredentials();
    Assert.assertEquals(1, creds.size());
    RequiredCredentialModel cred = creds.get(0);
    Assert.assertEquals("password", cred.getFormLabel());
    Assert.assertEquals(3, realm.getDefaultRoles().size());

    Assert.assertNotNull(realm.getRole("foo"));
    Assert.assertNotNull(realm.getRole("bar"));

    UserModel user = session.users().getUserByUsername("loginclient", realm);
    Assert.assertNotNull(user);
    Assert.assertEquals(0, session.users().getFederatedIdentities(user, realm).size());

    List<ClientModel> resources = realm.getClients();
    Assert.assertEquals(7, resources.size());

    // Test applications imported
    ClientModel application = realm.getClientByClientId("Application");
    ClientModel otherApp = realm.getClientByClientId("OtherApp");
    ClientModel accountApp = realm.getClientByClientId(Constants.ACCOUNT_MANAGEMENT_CLIENT_ID);
    ClientModel nonExisting = realm.getClientByClientId("NonExisting");
    Assert.assertNotNull(application);
    Assert.assertNotNull(otherApp);
    Assert.assertNull(nonExisting);
    Map<String, ClientModel> clients = realm.getClientNameMap();
    Assert.assertEquals(7, clients.size());
    Assert.assertTrue(clients.values().contains(application));
    Assert.assertTrue(clients.values().contains(otherApp));
    Assert.assertTrue(clients.values().contains(accountApp));
    realm.getClients().containsAll(clients.values());

    Assert.assertEquals("Applicationn", application.getName());
    Assert.assertEquals(50, application.getNodeReRegistrationTimeout());
    Map<String, Integer> appRegisteredNodes = application.getRegisteredNodes();
    Assert.assertEquals(2, appRegisteredNodes.size());
    Assert.assertTrue(10 == appRegisteredNodes.get("node1"));
    Assert.assertTrue(20 == appRegisteredNodes.get("172.10.15.20"));

    // test clientAuthenticatorType
    Assert.assertEquals(application.getClientAuthenticatorType(), "client-secret");
    Assert.assertEquals(otherApp.getClientAuthenticatorType(), "client-jwt");

    // Test finding applications by ID
    Assert.assertNull(realm.getClientById("982734"));
    Assert.assertEquals(application, realm.getClientById(application.getId()));

    // Test role mappings
    UserModel admin = session.users().getUserByUsername("admin", realm);
    // user without creation timestamp in import
    Assert.assertNull(admin.getCreatedTimestamp());
    Set<RoleModel> allRoles = admin.getRoleMappings();
    Assert.assertEquals(3, allRoles.size());
    Assert.assertTrue(allRoles.contains(realm.getRole("admin")));
    Assert.assertTrue(allRoles.contains(application.getRole("app-admin")));
    Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-admin")));

    Assert.assertTrue(application.getRole("app-admin").isScopeParamRequired());
    Assert.assertFalse(otherApp.getRole("otherapp-admin").isScopeParamRequired());
    Assert.assertFalse(otherApp.getRole("otherapp-user").isScopeParamRequired());

    UserModel wburke = session.users().getUserByUsername("wburke", realm);
    // user with creation timestamp in import
    Assert.assertEquals(new Long(123654), wburke.getCreatedTimestamp());
    allRoles = wburke.getRoleMappings();
    Assert.assertEquals(2, allRoles.size());
    Assert.assertFalse(allRoles.contains(realm.getRole("admin")));
    Assert.assertTrue(allRoles.contains(application.getRole("app-user")));
    Assert.assertTrue(allRoles.contains(otherApp.getRole("otherapp-user")));

    Assert.assertEquals(0, wburke.getRealmRoleMappings().size());

    UserModel loginclient = session.users().getUserByUsername("loginclient", realm);
    // user with creation timestamp as string in import
    Assert.assertEquals(new Long(123655), loginclient.getCreatedTimestamp());

    Set<RoleModel> realmRoles = admin.getRealmRoleMappings();
    Assert.assertEquals(1, realmRoles.size());
    Assert.assertEquals("admin", realmRoles.iterator().next().getName());

    Set<RoleModel> appRoles = admin.getClientRoleMappings(application);
    Assert.assertEquals(1, appRoles.size());
    Assert.assertEquals("app-admin", appRoles.iterator().next().getName());

    // Test attributes
    Map<String, List<String>> attrs = wburke.getAttributes();
    Assert.assertEquals(1, attrs.size());
    List<String> attrVals = attrs.get("email");
    Assert.assertEquals(1, attrVals.size());
    Assert.assertEquals("*****@*****.**", attrVals.get(0));

    attrs = admin.getAttributes();
    Assert.assertEquals(2, attrs.size());
    attrVals = attrs.get("key1");
    Assert.assertEquals(1, attrVals.size());
    Assert.assertEquals("val1", attrVals.get(0));
    attrVals = attrs.get("key2");
    Assert.assertEquals(2, attrVals.size());
    Assert.assertTrue(attrVals.contains("val21") && attrVals.contains("val22"));

    // Test client
    ClientModel oauthClient = realm.getClientByClientId("oauthclient");
    Assert.assertEquals("clientpassword", oauthClient.getSecret());
    Assert.assertEquals(true, oauthClient.isEnabled());
    Assert.assertNotNull(oauthClient);

    // Test scope relationship
    Set<RoleModel> allScopes = oauthClient.getScopeMappings();
    Assert.assertEquals(2, allScopes.size());
    Assert.assertTrue(allScopes.contains(realm.getRole("admin")));
    Assert.assertTrue(allScopes.contains(application.getRole("app-user")));

    Set<RoleModel> realmScopes = oauthClient.getRealmScopeMappings();
    Assert.assertTrue(realmScopes.contains(realm.getRole("admin")));

    Set<RoleModel> appScopes = application.getClientScopeMappings(oauthClient);
    Assert.assertTrue(appScopes.contains(application.getRole("app-user")));

    // Test social linking
    UserModel socialUser = session.users().getUserByUsername("mySocialUser", realm);
    Set<FederatedIdentityModel> socialLinks =
        session.users().getFederatedIdentities(socialUser, realm);
    Assert.assertEquals(3, socialLinks.size());
    boolean facebookFound = false;
    boolean googleFound = false;
    boolean twitterFound = false;
    for (FederatedIdentityModel federatedIdentityModel : socialLinks) {
      if ("facebook".equals(federatedIdentityModel.getIdentityProvider())) {
        facebookFound = true;
        Assert.assertEquals(federatedIdentityModel.getUserId(), "facebook1");
        Assert.assertEquals(federatedIdentityModel.getUserName(), "fbuser1");
      } else if ("google".equals(federatedIdentityModel.getIdentityProvider())) {
        googleFound = true;
        Assert.assertEquals(federatedIdentityModel.getUserId(), "google1");
        Assert.assertEquals(federatedIdentityModel.getUserName(), "*****@*****.**");
      } else if ("twitter".equals(federatedIdentityModel.getIdentityProvider())) {
        twitterFound = true;
        Assert.assertEquals(federatedIdentityModel.getUserId(), "twitter1");
        Assert.assertEquals(federatedIdentityModel.getUserName(), "twuser1");
      }
    }
    Assert.assertTrue(facebookFound && twitterFound && googleFound);

    UserModel foundSocialUser =
        session
            .users()
            .getUserByFederatedIdentity(
                new FederatedIdentityModel("facebook", "facebook1", "fbuser1"), realm);
    Assert.assertEquals(foundSocialUser.getUsername(), socialUser.getUsername());
    Assert.assertNull(
        session
            .users()
            .getUserByFederatedIdentity(
                new FederatedIdentityModel("facebook", "not-existing", "not-existing"), realm));

    FederatedIdentityModel foundSocialLink =
        session.users().getFederatedIdentity(socialUser, "facebook", realm);
    Assert.assertEquals("facebook1", foundSocialLink.getUserId());
    Assert.assertEquals("fbuser1", foundSocialLink.getUserName());
    Assert.assertEquals("facebook", foundSocialLink.getIdentityProvider());

    // Test removing social link
    Assert.assertTrue(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
    Assert.assertNull(session.users().getFederatedIdentity(socialUser, "facebook", realm));
    Assert.assertFalse(session.users().removeFederatedIdentity(realm, socialUser, "facebook"));
    session
        .users()
        .addFederatedIdentity(
            realm, socialUser, new FederatedIdentityModel("facebook", "facebook1", "fbuser1"));

    // Test smtp config
    Map<String, String> smtpConfig = realm.getSmtpConfig();
    Assert.assertTrue(smtpConfig.size() == 3);
    Assert.assertEquals("*****@*****.**", smtpConfig.get("from"));
    Assert.assertEquals("localhost", smtpConfig.get("host"));
    Assert.assertEquals("3025", smtpConfig.get("port"));

    // Test identity providers
    List<IdentityProviderModel> identityProviders = realm.getIdentityProviders();
    Assert.assertEquals(1, identityProviders.size());
    IdentityProviderModel google = identityProviders.get(0);
    Assert.assertEquals("google1", google.getAlias());
    Assert.assertEquals("google", google.getProviderId());
    Assert.assertTrue(google.isEnabled());
    Assert.assertEquals("googleId", google.getConfig().get("clientId"));
    Assert.assertEquals("googleSecret", google.getConfig().get("clientSecret"));

    // Test federation providers
    List<UserFederationProviderModel> fedProviders = realm.getUserFederationProviders();
    Assert.assertTrue(fedProviders.size() == 2);
    UserFederationProviderModel ldap1 = fedProviders.get(0);
    Assert.assertEquals("MyLDAPProvider1", ldap1.getDisplayName());
    Assert.assertEquals("ldap", ldap1.getProviderName());
    Assert.assertEquals(1, ldap1.getPriority());
    Assert.assertEquals("ldap://foo", ldap1.getConfig().get(LDAPConstants.CONNECTION_URL));

    UserFederationProviderModel ldap2 = fedProviders.get(1);
    Assert.assertEquals("MyLDAPProvider2", ldap2.getDisplayName());
    Assert.assertEquals("ldap://bar", ldap2.getConfig().get(LDAPConstants.CONNECTION_URL));

    // Test federation mappers
    Set<UserFederationMapperModel> fedMappers1 =
        realm.getUserFederationMappersByFederationProvider(ldap1.getId());
    Assert.assertTrue(fedMappers1.size() == 1);
    UserFederationMapperModel fullNameMapper = fedMappers1.iterator().next();
    Assert.assertEquals("FullNameMapper", fullNameMapper.getName());
    Assert.assertEquals(
        FullNameLDAPFederationMapperFactory.PROVIDER_ID, fullNameMapper.getFederationMapperType());
    Assert.assertEquals(ldap1.getId(), fullNameMapper.getFederationProviderId());
    Assert.assertEquals(
        "cn",
        fullNameMapper.getConfig().get(FullNameLDAPFederationMapper.LDAP_FULL_NAME_ATTRIBUTE));

    // All builtin LDAP mappers should be here
    Set<UserFederationMapperModel> fedMappers2 =
        realm.getUserFederationMappersByFederationProvider(ldap2.getId());
    Assert.assertTrue(fedMappers2.size() > 3);
    Set<UserFederationMapperModel> allMappers = realm.getUserFederationMappers();
    Assert.assertEquals(allMappers.size(), fedMappers1.size() + fedMappers2.size());

    // Assert that federation link wasn't created during import
    UserFederationProviderFactory factory =
        (UserFederationProviderFactory)
            session
                .getKeycloakSessionFactory()
                .getProviderFactory(UserFederationProvider.class, "dummy");
    Assert.assertNull(factory.getInstance(session, null).getUserByUsername(realm, "wburke"));

    // Test builtin authentication flows
    AuthenticationFlowModel clientFlow = realm.getClientAuthenticationFlow();
    Assert.assertEquals(
        DefaultAuthenticationFlows.CLIENT_AUTHENTICATION_FLOW, clientFlow.getAlias());
    Assert.assertNotNull(realm.getAuthenticationFlowById(clientFlow.getId()));
    Assert.assertTrue(realm.getAuthenticationExecutions(clientFlow.getId()).size() > 0);

    AuthenticationFlowModel resetFlow = realm.getResetCredentialsFlow();
    Assert.assertEquals(DefaultAuthenticationFlows.RESET_CREDENTIALS_FLOW, resetFlow.getAlias());
    Assert.assertNotNull(realm.getAuthenticationFlowById(resetFlow.getId()));
    Assert.assertTrue(realm.getAuthenticationExecutions(resetFlow.getId()).size() > 0);

    // Test protocol mappers. Default application has all the builtin protocol mappers. OtherApp
    // just gss credential
    Assert.assertNotNull(
        application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
    Assert.assertNotNull(
        application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "email"));
    Assert.assertNotNull(
        application.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "given name"));
    Assert.assertNull(
        application.getProtocolMapperByName(
            OIDCLoginProtocol.LOGIN_PROTOCOL,
            KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME));

    Assert.assertEquals(1, otherApp.getProtocolMappers().size());
    Assert.assertNull(
        otherApp.getProtocolMapperByName(OIDCLoginProtocol.LOGIN_PROTOCOL, "username"));
    ProtocolMapperModel gssCredentialMapper =
        otherApp.getProtocolMapperByName(
            OIDCLoginProtocol.LOGIN_PROTOCOL,
            KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME);
    Assert.assertEquals(
        KerberosConstants.GSS_DELEGATION_CREDENTIAL_DISPLAY_NAME, gssCredentialMapper.getName());
    Assert.assertEquals(OIDCLoginProtocol.LOGIN_PROTOCOL, gssCredentialMapper.getProtocol());
    Assert.assertEquals(UserSessionNoteMapper.PROVIDER_ID, gssCredentialMapper.getProtocolMapper());
    String includeInAccessToken =
        gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
    String includeInIdToken =
        gssCredentialMapper.getConfig().get(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
    Assert.assertTrue(includeInAccessToken.equalsIgnoreCase("true"));
    Assert.assertTrue(includeInIdToken == null || Boolean.parseBoolean(includeInIdToken) == false);

    // Test user consents
    admin = session.users().getUserByUsername("admin", realm);
    Assert.assertEquals(2, admin.getConsents().size());

    UserConsentModel appAdminConsent = admin.getConsentByClient(application.getId());
    Assert.assertEquals(2, appAdminConsent.getGrantedRoles().size());
    Assert.assertTrue(
        appAdminConsent.getGrantedProtocolMappers() == null
            || appAdminConsent.getGrantedProtocolMappers().isEmpty());
    Assert.assertTrue(appAdminConsent.isRoleGranted(realm.getRole("admin")));
    Assert.assertTrue(appAdminConsent.isRoleGranted(application.getRole("app-admin")));

    UserConsentModel otherAppAdminConsent = admin.getConsentByClient(otherApp.getId());
    Assert.assertEquals(1, otherAppAdminConsent.getGrantedRoles().size());
    Assert.assertEquals(1, otherAppAdminConsent.getGrantedProtocolMappers().size());
    Assert.assertTrue(otherAppAdminConsent.isRoleGranted(realm.getRole("admin")));
    Assert.assertFalse(otherAppAdminConsent.isRoleGranted(application.getRole("app-admin")));
    Assert.assertTrue(otherAppAdminConsent.isProtocolMapperGranted(gssCredentialMapper));

    // Test service accounts
    Assert.assertFalse(application.isServiceAccountsEnabled());
    Assert.assertTrue(otherApp.isServiceAccountsEnabled());
    Assert.assertNull(session.users().getUserByServiceAccountClient(application));
    UserModel linked = session.users().getUserByServiceAccountClient(otherApp);
    Assert.assertNotNull(linked);
    Assert.assertEquals("my-service-user", linked.getUsername());
  }
예제 #17
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);
    }
  }