-
2-2. OIDC 연동 - Spring FrameworkTutorials & Tips/WSO2 Identity Server 2022. 5. 12. 09:37
이번 게시글은 Spring Framework 기반의 어플리케이션을 WSO2의 OIDC와 연동하여 로그인을 진행하기 위한 과정입니다. 예제 실행 환경은 다음과 같습니다.
- Eclipse - Spring Framework 사용
- JDK 1.8
- Embedded Apache Tomcat (spring-boot-starter-tomcat-2.5.14)
- WSO2 IS 5.11, 샘플 소스 : 로컬환경 내 구축
1. Service Provider 등록
1-1. 생성
<그림 1> Service Provider - Add 먼저, WSO2 의 콘솔로 접근하여 Service Provider (이하 SP) 를 등록해줍니다.
해당 과정에서는 SP를 등록하여 Client ID / Secret 값을 발급받아야 합니다.
사진과 같이, 콘솔 좌측의 표시된 부분인 Service Providers - Add를 클릭하면 그림과 같은 창이 뜨는데,
이후 예제로 사용할 이름을 입력해준 뒤, Register를 클릭해 해당 SP를 등록해줍니다.
1-2. 조회
<그림 2> Service Provider - List 이후 List를 클릭하면 다음과 같이 SP가 등록된걸 확인할 수 있는데, 이후 Edit를 눌러 해당 SP의 설정탭에 접근합니다.
1-3. 수정
<그림 3> Service Provider - Edit (좌) / <그림 4> OAuth/OpenID Configuration (우) 기타 설정은 수정하지 않고, 하단의 Inbound Authentication Configuration - OAuth/OpenID Connect Configuration 탭의 Configure를 클릭해주면 우측 사진과 같은 화면이 출력되는데, 하단의 'Callback Url' 탭에 리다이렉트 할 URL을 작성해줍니다. 해당 예제에서는 "http://localhost:8080/login/oauth2/code/wso2" 를 입력해 주었습니다.
<그림 5> Client ID, Client Secret 이후 설정값을 저장하면 다음과 같이 Client Key, Secret값이 발급됩니다.
2. 샘플소스 생성
2-1. 프로젝트 생성
<그림 6> 프로젝트 생성 다음 구성과 같이, Spring Web, OAuth2 Client, Thymeleaf가 포함된 프로젝트를 생성하고, workspace로 import 합니다. 해당 예제에서는 start.spring.io 에서 프로젝트를 생성했습니다.
2-2. 라이브러리 추가 (pom.xml)
<!--Additional Dependencies--> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> <version>2.1.2.RELEASE</version> </dependency>
pom.xml에서 다음과 같이 라이브러리를 추가해줍니다.
2-3. Controller 생성 (IndexController.java)
package com.pharosinfo.oauth2loginsample; import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class IndexController { @GetMapping("/") public String getUserName(Model model, OAuth2AuthenticationToken token) { model.addAttribute("userName", token.getPrincipal().getName()); return "index"; } }
로그인 후 화면을 출력하기 위해 indexController class를 생성해줬습니다. index 페이지에서는 로그인한 사용자의 ID를 출력하고자 하므로, View에 매핑할 userName에 token.getPrincipal().getName() 을 작성해줍니다.
2-4. View 생성 (index.html)
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"> <html lang="en"> <head> <meta charset="UTF-8"> <title>OAuth2 Login </title> </head> <body> <div style="float: right"> <div style="float:left"> <span style="font-weight:bold">User: <span th:text=${userName}></span> </span> </div> <div style="float:none"> </div> <div style="float:right"> <form th:action="@{/logout}" method="post"> <input type="submit" value="Logout"/> </form> </div> </div> <h1>OAuth 2.0 Login with Spring Security</h1> <div> You are successfully logged in as <span style="font-weight:bold" th:text="${userName}"></span> </div> </body> </html>
로그인 성공 시 리턴될 View 입니다. 예시문 하단의 span 태그 안에 IndexController.java 로부터 userName이 매핑되도록 작성해줍니다.
2-5. 환경변수 추가 (application.properties)
#필수값-------------------------- spring.thymeleaf.cache=false spring.security.oauth2.client.registration.wso2.client-id=<발급받은 Client ID 입력> spring.security.oauth2.client.registration.wso2.client-secret=<발급받은 Client Secret 입력> spring.security.oauth2.client.provider.wso2.authorization-uri=http://localhost:9763/oauth2/authorize spring.security.oauth2.client.provider.wso2.token-uri=http://localhost:9763/oauth2/token spring.security.oauth2.client.provider.wso2.user-info-uri=http://localhost:9763/oauth2/userinfo spring.security.oauth2.client.provider.wso2.jwk-set-uri=http://localhost:9763/oauth2/jwks #선택값--------------------------for tomcat logfiles server.tomcat.accesslog.enabled=true server.tomcat.accesslog.suffix=.log server.tomcat.accesslog.prefix=access_log server.tomcat.accesslog.file-date-format=.yyyy-MM-dd server.tomcat.basedir=tomcat server.tomcat.accesslog.directory=logs server.tomcat.accesslog.pattern=common #선택값--------------------------for view internal logs of tomcat logging.level.org.apache.tomcat=DEBUG logging.level.org.apache.catalina=DEBUG
프로젝트 내의 application.properties 파일에 다음과 같이 Client ID, Secret, url 등 연결에 필요한 내용을 추가해줍니다. 선택값으로 표시된 server.tomcat과 관련된 설정은 디버깅을 위한 옵션으로, 필수사항은 아닙니다.
2-6. Repository 작성 (OAuth2LoginConfig.java)
package com.pharosinfo.oauth2loginsample; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.security.oauth2.client.registration.ClientRegistration; import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository; import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository; import org.springframework.security.oauth2.core.AuthorizationGrantType; import org.springframework.security.oauth2.core.ClientAuthenticationMethod; import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames; @Configuration public class OAuth2LoginConfig { private static String CLIENT_PROPERTY_KEY = "spring.security.oauth2.client.registration.wso2."; private static String PROVIDER_PROPERTY_KEY = "spring.security.oauth2.client.provider.wso2."; @Autowired private Environment env; @Bean public ClientRegistrationRepository clientRegistrationRepository() { return new InMemoryClientRegistrationRepository(this.WSO2ClientRegistration()); } private ClientRegistration WSO2ClientRegistration() { return ClientRegistration.withRegistrationId("wso2") .clientId(env.getProperty(CLIENT_PROPERTY_KEY + "client-id")) .clientSecret(env.getProperty(CLIENT_PROPERTY_KEY + "client-secret")) .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC) .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE) .redirectUri("{baseUrl}/login/oauth2/code/{registrationId}") .scope("openid", "profile", "email", "address", "phone") .authorizationUri(env.getProperty(PROVIDER_PROPERTY_KEY + "authorization-uri")) .tokenUri(env.getProperty(PROVIDER_PROPERTY_KEY + "token-uri")) .userInfoUri(env.getProperty(PROVIDER_PROPERTY_KEY + "user-info-uri")) .userNameAttributeName(IdTokenClaimNames.SUB) .jwkSetUri(env.getProperty(PROVIDER_PROPERTY_KEY + "jwk-set-uri")) .clientName("WSO2") .build(); } }
WSO2와 연결하기 위해 ClientRegistration 라이브러리를 사용, 환경변수를 참고하여 각 필수값을 설정해줍니다. 해당 함수에서는 scope, 로그인 페이지에 출력되는 clientName 등을 입력할 수 있습니다.
3. 실행
3-1. 메인페이지 접속
<그림 7> Client 선택 페이지 IDE 내에서 'Run as Spring boot App' 을 통해 해당 소스를 실행시킨 뒤 http://localhost:8080/login 으로 접속하면, 다음과 같은 화면이 출력됩니다. OAuth2LoginConfig.java 작성 당시 Repository 에 clientName 으로 등록한 'WSO2'를 확인할 수 있습니다. WSO2를 클릭하여 다음 단계인 로그인을 진행합니다.
3-2. 로그인
<그림 8> WSO2 로그인 페이지 (좌) / <그림 9> 접근권한 확인 페이지 (우) 로그인 계정을 입력하면 다음과 같이 접근권한을 묻는 창이 나타납니다. OAuth2LoginConfig.java 작성 당시 Repository 에 scope 로 등록한 4개의 항목에 대한 접근권한을 묻는걸 확인할 수 있습니다. Allow를 눌러 다음 단계로 진행합니다.
3-3. 로그인 확인
<그림 10> 메인 페이지 (index.html) 정상적으로 로그인이 진행되었다면, index.html로 이동하며 사용자 ID가 페이지에 출력되는걸 확인할 수 있습니다.
4. 참고링크
OAuth2 Login for Spring Boot Application with WSO2 Identity Server
Authentication and authorization is a crosscutting concern of application development. Outsourcing the authentication to 3 rd party…
medium.com
'Tutorials & Tips > WSO2 Identity Server' 카테고리의 다른 글
3. WSO2 IS-Salesforce 연동하기 (0) 2022.05.18 2-4. PKIX 에러 발생 시 해결방법 (0) 2022.05.13 2-3. OIDC 연동 - Vue.js (0) 2022.05.12 2-1-1. OIDC 연동 - JDK 1.8 (0) 2022.04.28 1. WSO2 Identity Server 설치 하기 (0) 2022.04.21