use of org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider in project syncope by apache.
the class OIDCC4UILogic method login.
@PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
public OIDCLoginResponse login(final String redirectURI, final String authorizationCode, final String opName) {
// 0. look for OP
OIDCC4UIProvider op = opDAO.findByName(opName);
if (op == null) {
throw new NotFoundException("OIDC Provider '" + opName + '\'');
}
// 1. look for configured client
OidcClient oidcClient = getOidcClient(opName, redirectURI);
oidcClient.setCallbackUrl(redirectURI);
// 2. get OpenID Connect tokens
String idTokenHint;
JWTClaimsSet idToken;
try {
OidcCredentials credentials = new OidcCredentials();
credentials.setCode(new AuthorizationCode(authorizationCode));
OIDC4UIContext ctx = new OIDC4UIContext();
oidcClient.getAuthenticator().validate(credentials, ctx, NoOpSessionStore.INSTANCE);
idToken = credentials.getIdToken().getJWTClaimsSet();
idTokenHint = credentials.getIdToken().serialize();
} catch (Exception e) {
LOG.error("While validating Token Response", e);
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
sce.getElements().add(e.getMessage());
throw sce;
}
// 3. prepare the result
OIDCLoginResponse loginResponse = new OIDCLoginResponse();
loginResponse.setLogoutSupported(StringUtils.isNotBlank(op.getEndSessionEndpoint()));
// 3a. find matching user (if any) and return the received attributes
String keyValue = idToken.getSubject();
for (OIDCC4UIProviderItem item : op.getItems()) {
Attr attrTO = new Attr();
attrTO.setSchema(item.getExtAttrName());
String value = idToken.getClaim(item.getExtAttrName()) == null ? null : idToken.getClaim(item.getExtAttrName()).toString();
if (value != null) {
attrTO.getValues().add(value);
loginResponse.getAttrs().add(attrTO);
if (item.isConnObjectKey()) {
keyValue = value;
}
}
}
List<String> matchingUsers = keyValue == null ? List.of() : userManager.findMatchingUser(keyValue, op.getConnObjectKeyItem().get());
LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
// 3b. not found: create or selfreg if configured
String username;
if (matchingUsers.isEmpty()) {
if (op.isCreateUnmatching()) {
LOG.debug("No user matching {}, about to create", keyValue);
String defaultUsername = keyValue;
username = AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(), () -> userManager.create(op, loginResponse, defaultUsername));
} else if (op.isSelfRegUnmatching()) {
UserTO userTO = new UserTO();
userManager.fill(op, loginResponse, userTO);
loginResponse.getAttrs().clear();
loginResponse.getAttrs().addAll(userTO.getPlainAttrs());
if (StringUtils.isNotBlank(userTO.getUsername())) {
loginResponse.setUsername(userTO.getUsername());
} else {
loginResponse.setUsername(keyValue);
}
loginResponse.setSelfReg(true);
return loginResponse;
} else {
throw new NotFoundException(Optional.ofNullable(keyValue).map(value -> "User matching the provided value " + value).orElse("User marching the provided claims"));
}
} else if (matchingUsers.size() > 1) {
throw new IllegalArgumentException("Several users match the provided value " + keyValue);
} else {
if (op.isUpdateMatching()) {
LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
username = AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(), () -> userManager.update(matchingUsers.get(0), op, loginResponse));
} else {
username = matchingUsers.get(0);
}
}
loginResponse.setUsername(username);
// 4. generate JWT for further access
Map<String, Object> claims = new HashMap<>();
claims.put(JWT_CLAIM_OP_NAME, opName);
claims.put(JWT_CLAIM_ID_TOKEN, idTokenHint);
byte[] authorities = null;
try {
authorities = ENCRYPTOR.encode(POJOHelper.serialize(authDataAccessor.getAuthorities(loginResponse.getUsername(), null)), CipherAlgorithm.AES).getBytes();
} catch (Exception e) {
LOG.error("Could not fetch authorities", e);
}
Pair<String, OffsetDateTime> accessTokenInfo = accessTokenDataBinder.create(loginResponse.getUsername(), claims, authorities, true);
loginResponse.setAccessToken(accessTokenInfo.getLeft());
loginResponse.setAccessTokenExpiryTime(accessTokenInfo.getRight());
return loginResponse;
}
use of org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider in project syncope by apache.
the class OIDCC4UIProviderLogic method update.
@PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_UPDATE + "')")
public void update(final OIDCC4UIProviderTO opTO) {
OIDCC4UIProvider op = opDAO.find(opTO.getKey());
if (op == null) {
throw new NotFoundException("OIDC Provider '" + opTO.getKey() + '\'');
}
if (!op.getIssuer().equals(opTO.getIssuer())) {
LOG.error("Issuers do not match: expected {}, found {}", op.getIssuer(), opTO.getIssuer());
SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidEntity);
sce.getElements().add("Issuers do not match");
throw sce;
}
String opName = op.getName();
opDAO.save(binder.update(op, opTO));
oidcClientClientCache.removeAll(opName);
}
use of org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider in project syncope by apache.
the class OIDCC4UIProviderLogic method create.
@PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_CREATE + "')")
public String create(final OIDCC4UIProviderTO opTO) {
if (opTO.getConnObjectKeyItem() == null) {
ItemTO connObjectKeyItem = new ItemTO();
connObjectKeyItem.setIntAttrName("username");
connObjectKeyItem.setExtAttrName("email");
opTO.setConnObjectKeyItem(connObjectKeyItem);
}
OIDCC4UIProvider provider = opDAO.save(binder.create(opTO));
return provider.getKey();
}
use of org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider in project syncope by apache.
the class OIDCC4UIProviderLogic method delete.
@PreAuthorize("hasRole('" + OIDC4UIEntitlement.OP_DELETE + "')")
public void delete(final String key) {
OIDCC4UIProvider op = opDAO.find(key);
if (op == null) {
throw new NotFoundException("OIDC Provider '" + key + '\'');
}
String opName = op.getName();
opDAO.delete(key);
oidcClientClientCache.removeAll(opName);
}
use of org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider in project syncope by apache.
the class JPAOIDCC4UIProviderDAO method findByName.
@Transactional(readOnly = true)
@Override
public OIDCC4UIProvider findByName(final String name) {
TypedQuery<OIDCC4UIProvider> query = entityManager().createQuery("SELECT e FROM " + JPAOIDCC4UIProvider.class.getSimpleName() + " e WHERE e.name = :name", OIDCC4UIProvider.class);
query.setParameter("name", name);
OIDCC4UIProvider result = null;
try {
result = query.getSingleResult();
} catch (NoResultException e) {
LOG.debug("No OIDC Provider found with name {}", name, e);
}
return result;
}
Aggregations