|
| 1 | +package com.workastra.iam; |
| 2 | + |
| 3 | +import java.time.Duration; |
| 4 | +import java.util.concurrent.TimeoutException; |
| 5 | +import org.slf4j.Logger; |
| 6 | +import org.slf4j.LoggerFactory; |
| 7 | +import org.springframework.boot.ApplicationArguments; |
| 8 | +import org.springframework.boot.ApplicationRunner; |
| 9 | +import org.springframework.boot.security.oauth2.server.authorization.autoconfigure.servlet.OAuth2AuthorizationServerProperties; |
| 10 | +import org.springframework.integration.support.locks.DistributedLock; |
| 11 | +import org.springframework.integration.support.locks.LockRegistry; |
| 12 | +import org.springframework.security.crypto.password.PasswordEncoder; |
| 13 | +import org.springframework.security.oauth2.core.AuthorizationGrantType; |
| 14 | +import org.springframework.security.oauth2.core.ClientAuthenticationMethod; |
| 15 | +import org.springframework.security.oauth2.server.authorization.client.RegisteredClient; |
| 16 | +import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository; |
| 17 | +import org.springframework.security.oauth2.server.authorization.settings.ClientSettings; |
| 18 | +import org.springframework.stereotype.Component; |
| 19 | + |
| 20 | +@Component |
| 21 | +public class Bootstrap implements ApplicationRunner { |
| 22 | + |
| 23 | + private static final Logger logger = LoggerFactory.getLogger(Bootstrap.class); |
| 24 | + private final RegisteredClientRepository registeredClientRepository; |
| 25 | + private final OAuth2AuthorizationServerProperties properties; |
| 26 | + private final PasswordEncoder passwordEncoder; |
| 27 | + private final LockRegistry<DistributedLock> lockRegistry; |
| 28 | + |
| 29 | + public Bootstrap( |
| 30 | + LockRegistry<DistributedLock> lockRegistry, |
| 31 | + RegisteredClientRepository registeredClientRepository, |
| 32 | + OAuth2AuthorizationServerProperties properties, |
| 33 | + PasswordEncoder passwordEncoder |
| 34 | + ) { |
| 35 | + this.lockRegistry = lockRegistry; |
| 36 | + this.registeredClientRepository = registeredClientRepository; |
| 37 | + this.properties = properties; |
| 38 | + this.passwordEncoder = passwordEncoder; |
| 39 | + } |
| 40 | + |
| 41 | + @Override |
| 42 | + public void run(ApplicationArguments args) throws InterruptedException, TimeoutException { |
| 43 | + this.lockRegistry.executeLocked("iam.migration", Duration.ofSeconds(30), () -> { |
| 44 | + logger.info("Acquired lock for client registration migration"); |
| 45 | + |
| 46 | + var clients = this.properties.getClient(); |
| 47 | + |
| 48 | + logger.info("Upserting {} client(s) from application properties", clients.size()); |
| 49 | + |
| 50 | + for (var client : clients.entrySet()) { |
| 51 | + var id = client.getKey(); |
| 52 | + var value = client.getValue(); |
| 53 | + |
| 54 | + logger.info("Registering client with id: {}", id); |
| 55 | + |
| 56 | + var registration = value.getRegistration(); |
| 57 | + RegisteredClient registeredClient = RegisteredClient.withId(id) |
| 58 | + .clientName(registration.getClientName()) |
| 59 | + .clientId(registration.getClientId()) |
| 60 | + .clientSecret( |
| 61 | + registration.getClientSecret() == null |
| 62 | + ? "" |
| 63 | + : this.passwordEncoder.encode(registration.getClientSecret()) |
| 64 | + ) |
| 65 | + .clientAuthenticationMethods(methods -> { |
| 66 | + methods.clear(); |
| 67 | + registration |
| 68 | + .getClientAuthenticationMethods() |
| 69 | + .forEach(method -> methods.add(ClientAuthenticationMethod.valueOf(method))); |
| 70 | + }) |
| 71 | + .authorizationGrantTypes(types -> { |
| 72 | + types.clear(); |
| 73 | + registration |
| 74 | + .getAuthorizationGrantTypes() |
| 75 | + .forEach(type -> types.add(new AuthorizationGrantType(type))); |
| 76 | + }) |
| 77 | + .redirectUris(uris -> { |
| 78 | + uris.clear(); |
| 79 | + uris.addAll(registration.getRedirectUris()); |
| 80 | + }) |
| 81 | + .scopes(scopes -> { |
| 82 | + scopes.clear(); |
| 83 | + scopes.addAll(registration.getScopes()); |
| 84 | + }) |
| 85 | + .postLogoutRedirectUris(uris -> { |
| 86 | + uris.clear(); |
| 87 | + uris.addAll(registration.getPostLogoutRedirectUris()); |
| 88 | + }) |
| 89 | + .clientSettings( |
| 90 | + ClientSettings.builder() |
| 91 | + .requireAuthorizationConsent(value.isRequireAuthorizationConsent()) |
| 92 | + .requireProofKey(value.isRequireProofKey()) |
| 93 | + .build() |
| 94 | + ) |
| 95 | + .build(); |
| 96 | + |
| 97 | + this.registeredClientRepository.save(registeredClient); |
| 98 | + |
| 99 | + logger.info("Client with id: {} registered successfully", registration.getClientId()); |
| 100 | + } |
| 101 | + }); |
| 102 | + } |
| 103 | +} |
0 commit comments