Skip to main content

SSO

Applications on CETA support not only username and password login but also standard SSO protocols such as OAuth2, CAS, and OIDC.

1. Documentation

Please familiarize yourself with the SSO protocols you intend to implement:

  1. OAuth2:
  2. OIDC:
  3. CAS:

2. Principle

If you have thoroughly read the above SSO protocols, as a client, you only need to focus on how to invoke the authentication service (i.e., redirect_uri) and the callback after authentication completion (i.e., callback, which determines the user). CETA provides extensions for redirect_url and callback.

3. Usage Steps

3.1 Configure Login

Configure the login method. For details, see the figure below:

  1. Unique Identifier: A unique identifier.
  2. Auth Type: Use basic for username and password login; for SSO, choose any relevant type.
  3. Login Property: Only required for basic, indicating which field in the user table to match, usually email or nickname.
  4. Need Captcha: Whether to require a captcha, only effective for basic.
  5. Hide: Whether to display.
  6. Default: Whether it is the default login method.
  7. Order: Display order.

Login-config The display effect after configuration: Login

3.2 Configure the redirect_url Flow

  1. REST Trigger Requirements:
    • Must be a REST-Flow.
    • Use a POST request.
    • Requires one input parameter:
      • loginMethod: The current login method, corresponding to the configuration in 3.1.
  2. Flow Output Settings:
    • The output key must be redirectUrl, containing the address of the third-party authentication service.

Redirect Url

3.3 Configure the callback Flow

  1. REST Trigger Requirements:
    • Must be a REST-Flow.
    • Use a POST request.
    • Requires two input parameters:
      • loginMethod: The current login method, corresponding to the configuration in 3.1.
      • callback: The content returned by the authentication service.
  2. Flow Output Settings:
    • Must include the following four values:
      • ssoUserId: The unique identifier of the SSO user.
      • ssoType: The Auth Type from the configuration in 3.1.
      • ssoEmail: The user's email.
      • ssoPhone: The user's phone number.
  • Callback

3.4 Configure Users

User

  1. Login Type: The type of SSO supported, corresponding to the sso_type in the user table.
  2. Unified Login Username: The unique identifier of the SSO user, corresponding to the sso_username in the user table.
  3. Allow Local Login: Whether to allow login with username and password, corresponding to the sso_allow_builtin in the user table.

3.5 User Matching

  1. User Matching Logic getSsoMappedUser:
    • Find the user by ssoUserId, ssoType, and projectToken.
    • First, try to match sso_type and sso_username.
    • If no user is found, check if ssoUserId contains @:
      • If it is an email address, match sso_type and email.
      • Otherwise, match sso_type and username.
    • Filter out users with an empty sso_username.
    • If multiple users are found, throw an exception.
    • If no user is found, return null.
    • Return the found user (if any).
  2. Matching Steps:
    • First, match using the ssoUserId from 3.3.
    • If no user is found and the ssoEmail from 3.3 is not empty, then match using the ssoEmail.

The matching rules are described in detail in the code:

// User Matching
private UserPo getSsoMappedUser(String ssoUserId, String ssoType, String projectToken) {
List<UserPo> users = userManagementRepository.findUserByProperties(
projectToken, Map.of(
"sso_type", ssoType,
"sso_username", ssoUserId
));
if (users.isEmpty()) {
if (ssoUserId.contains("@")) {
users = userManagementRepository.findUserByProperties(
projectToken, Map.of(
"sso_type", ssoType,
"email", ssoUserId
));
} else {
users = userManagementRepository.findUserByProperties(
projectToken, Map.of(
"sso_type", ssoType,
"username", ssoUserId
));
}
users = users.stream().filter(userPo -> StringUtils.isBlank(userPo.getSsoUsername())).collect(Collectors.toList());
}
if (users.size() > 1) {
throw new IllegalArgumentException("More than 1 user can login with ssoType: " + ssoType + " ssoId: " + ssoUserId);
}
if (users.isEmpty()) {
return null;
}
return users.get(0);
}

// loginMethodToken is the selected authentication type
// First, match using the ssoUserId returned in **3.3**
UserPo user = getSsoMappedUser(ssoUserInfo.getSsoUserId(), loginMethodToken, projectToken);
if (null == user && ssoUserInfo.getSsoEmail() != null) {
// If no user is found, match using the ssoEmail returned in **3.3**
user = getSsoMappedUser(ssoUserInfo.getSsoEmail(), loginMethodToken, projectToken);
}