{"id":3792,"date":"2021-11-08T22:56:17","date_gmt":"2021-11-08T13:56:17","guid":{"rendered":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=3792"},"modified":"2021-11-09T23:26:31","modified_gmt":"2021-11-09T14:26:31","slug":"spring-authorization-serveroauth2-customizing","status":"publish","type":"post","link":"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=3792","title":{"rendered":"spring-authorization-server(Oauth2) Customizing"},"content":{"rendered":"<h1>spring-authorization-server(Oauth2) Customizing<\/h1>\n<p><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=3786\">\ucc38\uc870<\/a> \ub97c \uae30\ubc18\uc73c\ub85c \uc6b4\uc601\uc11c\ubc84 \uc801\uc6a9 \uac00\ub2a5\ud55c\uc9c0 \ud14c\uc2a4\ud2b8 \ud574\ubd05\ub2c8\ub2e4.<\/p>\n<h2>Use MySQL<\/h2>\n<p>build.gradle<\/p>\n<pre><code class=\"language-gradle\">dependencies {\n    \/\/ runtimeOnly &#039;com.h2database:h2&#039;\n    runtimeOnly &#039;mysql:mysql-connector-java:8.0.25&#039;\n}<\/code><\/pre>\n<h2>application.yml<\/h2>\n<pre><code class=\"language-yaml\">server:\n  port: 9000\n\nspring:\n  datasource:\n    url: jdbc:mysql:\/\/${MYSQL_HOST:localhost}:3306\/db_oauth2_test\n    username: root\n    password:\n    driver-class-name: com.mysql.cj.jdbc.Driver\n  jpa:\n    hibernate:\n      ddl-auto: update    # \uac1c\ubc1c\uc6a9 only\n    show-sql: true\n\nlogging:\n  level:\n    root: INFO\n    org.springframework.web: INFO\n    org.springframework.security: INFO\n    org.springframework.security.oauth2: INFO\n#    org.springframework.boot.autoconfigure: DEBUG<\/code><\/pre>\n<h2>\uc2a4\ud0a4\ub9c8 \uc0dd\uc131<\/h2>\n<p>\uc2a4\ud0a4\ub9c8\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-sql\">CREATE DATABASE `db_oauth2_test`;<\/code><\/pre>\n<pre><code class=\"language-sql\">CREATE TABLE oauth2_registered_client (\n    id varchar(100) NOT NULL,\n    client_id varchar(100) NOT NULL,\n    client_id_issued_at timestamp DEFAULT CURRENT_TIMESTAMP NOT NULL,\n    client_secret varchar(200) DEFAULT NULL,\n    client_secret_expires_at TIMESTAMP NULL DEFAULT NULL,\n    client_name varchar(200) NOT NULL,\n    client_authentication_methods varchar(1000) NOT NULL,\n    authorization_grant_types varchar(1000) NOT NULL,\n    redirect_uris varchar(1000) DEFAULT NULL,\n    scopes varchar(1000) NOT NULL,\n    client_settings varchar(2000) NOT NULL,\n    token_settings varchar(2000) NOT NULL,\n    PRIMARY KEY (id)\n);\n\nCREATE TABLE oauth2_authorization_consent (\n    registered_client_id varchar(100) NOT NULL,\n    principal_name varchar(200) NOT NULL,\n    authorities varchar(1000) NOT NULL,\n    PRIMARY KEY (registered_client_id, principal_name)\n);\n\nCREATE TABLE oauth2_authorization (\n    id varchar(100) NOT NULL,\n    registered_client_id varchar(100) NOT NULL,\n    principal_name varchar(200) NOT NULL,\n    authorization_grant_type varchar(100) NOT NULL,\n    attributes varchar(4000) DEFAULT NULL,\n    state varchar(500) DEFAULT NULL,\n    authorization_code_value blob DEFAULT NULL,\n    authorization_code_issued_at timestamp NULL DEFAULT NULL,\n    authorization_code_expires_at timestamp NULL DEFAULT NULL,\n    authorization_code_metadata varchar(2000) DEFAULT NULL,\n    access_token_value blob DEFAULT NULL,\n    access_token_issued_at timestamp NULL DEFAULT NULL,\n    access_token_expires_at timestamp NULL DEFAULT NULL,\n    access_token_metadata varchar(2000) DEFAULT NULL,\n    access_token_type varchar(100) DEFAULT NULL,\n    access_token_scopes varchar(1000) DEFAULT NULL,\n    oidc_id_token_value blob DEFAULT NULL,\n    oidc_id_token_issued_at timestamp NULL DEFAULT NULL,\n    oidc_id_token_expires_at timestamp NULL DEFAULT NULL,\n    oidc_id_token_metadata varchar(2000) DEFAULT NULL,\n    refresh_token_value blob DEFAULT NULL,\n    refresh_token_issued_at timestamp NULL DEFAULT NULL,\n    refresh_token_expires_at timestamp NULL DEFAULT NULL,\n    refresh_token_metadata varchar(2000) DEFAULT NULL,\n    PRIMARY KEY (id)\n);\n\nCREATE TABLE users (\n    id INT(10) NOT NULL AUTO_INCREMENT,\n    username VARCHAR(100) NOT NULL,\n    password VARCHAR(200) DEFAULT NULL,\n    enabled BOOLEAN NOT NULL,\n    acc_locked BOOLEAN NULL,\n    acc_expired BOOLEAN NULL,\n    creds_expired BOOLEAN NULL,\n    PRIMARY KEY (id)\n);\n\nCREATE TABLE authorities (\n    id INT(10) NOT NULL AUTO_INCREMENT,\n    username VARCHAR(100) NOT NULL,\n    authority VARCHAR(200) NOT NULL,\n    PRIMARY KEY (id)\n);<\/code><\/pre>\n<h2>AuthorizationServerConfig.java<\/h2>\n<pre><code class=\"language-java\">@Configuration(proxyBeanMethods = false)\npublic class AuthorizationServerConfig {\n\n    @Bean\n    @Order(Ordered.HIGHEST_PRECEDENCE)\n    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {\n        OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);\n        return http.formLogin(Customizer.withDefaults()).build();\n    }\n\n    \/\/ @formatter:off\n    @Bean\n    public RegisteredClientRepository registeredClientRepository(JdbcTemplate jdbcTemplate) {\n        RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())\n                .clientId(&quot;messaging-client&quot;)\n                .clientSecret(&quot;secret&quot;)\n                .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)\n                .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)\n                .authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)\n                .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)\n                .redirectUri(&quot;http:\/\/127.0.0.1:8080\/login\/oauth2\/code\/messaging-client-oidc&quot;)\n                .redirectUri(&quot;http:\/\/127.0.0.1:8080\/authorized&quot;)\n                .scope(OidcScopes.OPENID)\n                .scope(&quot;message.read&quot;)\n                .scope(&quot;message.write&quot;)\n                .clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())\n                .build();\n\n        \/\/ Save registered client in db as if in-memory\n        JdbcRegisteredClientRepository registeredClientRepository = new JdbcRegisteredClientRepository(jdbcTemplate);\n        JdbcRegisteredClientRepository.RegisteredClientParametersMapper registeredClientParametersMapper = new JdbcRegisteredClientRepository.RegisteredClientParametersMapper();\n        PasswordEncoder encoder = new BCryptPasswordEncoder();\n        registeredClientParametersMapper.setPasswordEncoder(encoder);\n        registeredClientRepository.setRegisteredClientParametersMapper(registeredClientParametersMapper);\n        registeredClientRepository.save(registeredClient);\n\n        return registeredClientRepository;\n    }\n    \/\/ @formatter:on\n\n    @Bean\n    public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {\n        return new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);\n    }\n\n    @Bean\n    public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {\n        return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository);\n    }\n\n    @Bean\n    public JWKSource&lt;SecurityContext&gt; jwkSource() {\n        RSAKey rsaKey = Jwks.generateRsa();\n        JWKSet jwkSet = new JWKSet(rsaKey);\n        return (jwkSelector, securityContext) -&gt; jwkSelector.select(jwkSet);\n    }\n\n    @Bean\n    public ProviderSettings providerSettings() {\n        return ProviderSettings.builder().issuer(&quot;http:\/\/auth-server:9000&quot;).build();\n    }\n}<\/code><\/pre>\n<h2>DefaultSecurityConfig.java<\/h2>\n<pre><code class=\"language-java\">@EnableWebSecurity\npublic class DefaultSecurityConfig {\n\n    private final DataSource dataSource;\n\n    @Bean\n    public PasswordEncoder bCryptPasswordEncoder() {\n        return new BCryptPasswordEncoder();\n    }\n\n    public DefaultSecurityConfig(DataSource dataSource) {\n        this.dataSource = dataSource;\n    }\n\n    \/\/ @formatter:off\n    @Bean\n    SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {\n        http\n            .authorizeRequests(authorizeRequests -&gt;\n                authorizeRequests.anyRequest().authenticated()\n            )\n            .formLogin(withDefaults());\n        return http.build();\n    }\n    \/\/ @formatter:on\n\n    \/\/ @formatter:off\n    @Bean\n    UserDetailsService users() {\n        JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);\n\n        try {\n            UserDetails user = jdbcUserDetailsManager.loadUserByUsername(&quot;user1&quot;);\n        } catch (UsernameNotFoundException ex) {\n            PasswordEncoder encoder = new BCryptPasswordEncoder();\n            UserDetails user = User\n                    .withUsername(&quot;user1&quot;)\n                    .passwordEncoder(encoder::encode)\n                    .password(&quot;password&quot;)\n                    .roles(&quot;USER&quot;)\n                    .build();\n            jdbcUserDetailsManager.createUser(user);\n        }\n\n        return jdbcUserDetailsManager;\n    }\n    \/\/ @formatter:on\n}<\/code><\/pre>\n<h2>\ud504\ub85c\uc81d\ud2b8 \uc7ac\uc2e4\ud589<\/h2>\n<p>\ud504\ub85c\uc81d\ud2b8 \uc885\ub8cc \ud6c4 \ub2e4\uc2dc \uc2e4\ud589\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"language-sql\">SELECT * FROM oauth2_registered_client\nSELECT * FROM oauth2_authorization_consent\nSELECT * FROM oauth2_authorization\n\nSELECT * FROM users;\nSELECT * FROM authorities;<\/code><\/pre>\n<p><a href=\"http:\/\/localhost:8080\/\">http:\/\/localhost:8080\/<\/a> \uc5d0 \uc811\uc18d\ud574\uc11c \ub85c\uadf8\uc778\uc774 \uac00\ub2a5\ud55c \uac83\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<h2>\ub290\ub080\uc810<\/h2>\n<p>\ubb38\uc11c\uac00 \uc5c6\ub2e4.<br \/>\n\uadc0\ucc2e\uc544\uc11c \uc548\ub9cc\ub4e4\uc5c8\ub2e4\uae30\ubcf4\ub2e4\ub294 API \uc790\uccb4\uac00 \ubcc0\ud560 \uac00\ub2a5\uc131\uc774 \ub108\ubb34 \ub192\uc544 \uc791\uc131\ud558\uc9c0 \ubabb\ud55c\ub2e4\ub294 \ub290\ub08c\uc774\ub2e4.<\/p>\n<p>\uc18c\uc2a4\uac00 \uc544\uc9c1 \uae54\ub054\ud558\uc9c0 \uc54a\ub2e4.<\/p>\n<p>\uc6b4\uc601\uc11c\ubc84\uc5d0 \uc801\uc6a9\ud558\uae30\uc5d0\ub294 \uc704\ud5d8\ubd80\ub2f4\uc774 \ub108\ubb34 \ub9ce\ub2e4.<\/p>\n<p>\ub290\ub08c\uc0c1 \uc774 \ud504\ub85c\uc81d\ud2b8\uac00 \uc548\uc815\ud654\ub420\ub54c\uae4c\uc9c0\ub294 spring boot oauth2 \uac00 \ub0a0\ub77c\uac08 \uac00\ub2a5\uc131\uc740 \uc5c6\uc5b4 \ubcf4\uc774\ub2c8,<br \/>\nspring boot oauth2 \uac00 \uc0ac\ub77c\uc9c0\ub294 \uc77c\uc740 \uc5c6\uc744 \uac83 \uac19\uace0&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>spring-authorization-server(Oauth2) Customizing \ucc38\uc870 \ub97c \uae30\ubc18\uc73c\ub85c \uc6b4\uc601\uc11c\ubc84 \uc801\uc6a9 \uac00\ub2a5\ud55c\uc9c0 \ud14c\uc2a4\ud2b8 \ud574\ubd05\ub2c8\ub2e4. Use MySQL build.gradle dependencies { \/\/ runtimeOnly &#039;com.h2database:h2&#039; runtimeOnly &#039;mysql:mysql-connector-java:8.0.25&#039; } application.yml server: port: 9000 spring: datasource: url: jdbc:mysql:\/\/${MYSQL_HOST:localhost}:3306\/db_oauth2_test username: root password: driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: ddl-auto: update # \uac1c\ubc1c\uc6a9 only show-sql: true logging: level: root: INFO org.springframework.web: INFO org.springframework.security: INFO org.springframework.security.oauth2: INFO # org.springframework.boot.autoconfigure:\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.skyer9.pe.kr\/wordpress\/?p=3792\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29],"tags":[],"class_list":["post-3792","post","type-post","status-publish","format-standard","hentry","category-spring-boot-2-5"],"_links":{"self":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/3792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3792"}],"version-history":[{"count":15,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/3792\/revisions"}],"predecessor-version":[{"id":3812,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=\/wp\/v2\/posts\/3792\/revisions\/3812"}],"wp:attachment":[{"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.skyer9.pe.kr\/wordpress\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}