Java 애플리케이션과 Oracle Identity Cloud Service 간의 인증에 대해 알아보기
이제 Java 웹 애플리케이션과 Oracle Identity Cloud Service 간의 인증에 대해 알아볼 수 있습니다. 여기에는 다음 사항을 이해하는 것이 포함됩니다.
-
Oracle Identity Cloud Service가 Java SDK에 대해 지원하는 3단계 인증 플로우입니다.
-
Java 애플리케이션과 함께 SDK를 사용하여 Oracle Identity Cloud Service로 인증하는 사용 사례
-
Java SDK의 메소드 및 기능
3단계 인증 플로우에 대해 알아보기
Oracle Identity Cloud Service는 Java SDK에 대한 3단계 인증 플로우를 지원합니다. 이 플로우에서 사용자는 Oracle Identity Cloud Service와 직접 상호작용합니다. 사용자가 사인인한 후 Oracle Identity Cloud Service는 SDK가 사용자 액세스 토큰을 교환하는 권한 부여 코드를 발행합니다. Java 웹 애플리케이션은 이 액세스 토큰을 사용하여 애플리케이션에서 보호된 리소스에 대한 액세스 권한을 사용자에게 부여합니다. 3단계 플로우는 권한 부여 코드 권한 부여 유형을 사용합니다.
보안을 강화하기 위해 Oracle은 3단계 플로우를 사용하여 인증을 위해 Java 웹 애플리케이션을 Oracle Identity Cloud Service와 통합할 것을 권장합니다. 권한 부여 코드 유형을 사용하여 재인증할 필요 없이 Oracle Identity Cloud Service로 보호되는 다른 애플리케이션에 액세스할 수도 있습니다.
Java 애플리케이션에서 SDK를 사용하는 주요 사용 사례에 대해 알아보기
Java 웹 응용 프로그램은 두 가지 사용 사례를 구현합니다. 하나는 사용자 인증용이고 다른 하나는 로그인한 사용자에 대한 세부 정보에 액세스하기 위한 것입니다.
다음 데이터 플로우 다이어그램은 각 사용 사례에 대한 웹 브라우저, 웹 애플리케이션 및 Oracle Identity Cloud Service 간의 이벤트, 호출 및 응답 플로우를 보여 줍니다.
사용 사례 #1: 사용자 인증
데이터 흐름은 다음과 같이 발생합니다.
-
사용자가 보호된 리소스를 요청합니다.
-
인증 모듈은 SDK를 사용하여 Oracle Identity Cloud Service에 대한 요청 권한 부여 코드 URL을 생성하고 이 URL을 웹 브라우저에 재지정 응답으로 전송합니다.
-
웹 브라우저가 URL을 호출합니다.
-
Oracle Identity Cloud Service 사인인 페이지가 나타납니다.
-
사용자가 Oracle Identity Cloud Service 사인인 인증서를 제출합니다.
-
사용자가 사인인한 후 Oracle Identity Cloud Service는 사용자에 대한 세션을 생성하고 권한 부여 코드를 발행합니다.
-
웹 응용 프로그램은 액세스 토큰에 대한 권한 부여 코드를 교환하기 위해 백엔드(또는 서버 간) 호출을 수행합니다.
-
Oracle Identity Cloud Service가 액세스 토큰 및 ID 토큰을 발행합니다.
-
세션이 설정되고 사용자가 홈 페이지로 재지정됩니다.
-
웹 애플리케이션의 홈 페이지가 나타납니다.
사용 사례 #2: 사용자에 대한 세부정보 가져오기
데이터 흐름은 다음과 같이 발생합니다.
-
사용자가
/myProfile
리소스를 요청합니다. -
웹 애플리케이션은 Oracle Identity Cloud Service의 SDK를 사용하여 ID 토큰을 검증합니다.
-
ID 토큰 검증에서 반환되는 데이터는 JSON 객체 형식의 사용자 세부정보를 포함합니다.
-
내 프로파일 페이지는 JSON 객체를 HTML 콘텐츠로 렌더링합니다.
메소드 및 함수에 대해 알아보기
Java SDK는 웹 애플리케이션 라이브러리로 로드하는 JAR 파일입니다. 이 JAR 파일에는 라이브러리에 로드해야 하는 다음과 같은 타사 라이브러리가 필요합니다.
Java SDK zip 파일에는 SDK에 필요한 다음과 같은 타사 라이브러리가 포함되어 있습니다. 응용 프로그램으로 로드할 수 있습니다.
-
ASM 도우미 Minidev 1.0.2
-
Apache Commons 모음 4.1
-
Apache Commons 언어 3.7
-
JSON 작고 빠른 구문 분석기 2.3
-
님부스 LangTag 1.4.3
-
님부스 JOSE+JWT 5.14
-
OAuth 2.0 SDK(OpenID Connect 확장 기능 포함) 5.30
Oracle은 Java SDK 사용 방법을 보여주는 샘플 Java 웹 애플리케이션을 제공합니다. 이 애플리케이션은 Java SDK의 작동 방식을 이해하기 위해 학습 환경을 단순화하기 위해 서블릿 기술을 사용하여 구축되었습니다. 이 응용 프로그램은 Maven을 사용하여 모든 라이브러리를 가져오고 WAR(Web Application Resource) 파일을 생성합니다.
Java SDK를 사용하려면 Oracle Identity Cloud Service 접속 정보와 함께 로드된 HashMap
객체 인스턴스가 필요합니다. Java 웹 응용 프로그램은 이 HashMap
인스턴스를 ConnectionOptions.java
클래스의 클래스 속성으로 구현합니다.
//Instance of a HashMap.
private Map<String,Object> options = new HashMap<>();
public ConnectionOptions(){
this.options = new HashMap<>();
}
public Map<String,Object> getOptions(){
//Adding Oracle Identity Cloud Service connection parameters to the HashMap instance.
this.options.put(IDCSTokenAssertionConfiguration.IDCS_HOST, "identity.oraclecloud.com");
this.options.put(IDCSTokenAssertionConfiguration.IDCS_PORT, "443");
this.options.put(IDCSTokenAssertionConfiguration.IDCS_CLIENT_ID, "123456789abcdefghij");
this.options.put(IDCSTokenAssertionConfiguration.IDCS_CLIENT_SECRET, "abcde-12345-zyxvu-98765-qwerty");
this.options.put(IDCSTokenAssertionConfiguration.IDCS_CLIENT_TENANT, "idcs-abcd1234");
this.options.put(Constants.AUDIENCE_SERVICE_URL, "https://idcs-abcd1234.identity.oraclecloud.com");
this.options.put(Constants.TOKEN_ISSUER, "https://identity.oraclecloud.com/");
this.options.put(Constants.TOKEN_CLAIM_SCOPE, "urn:opc:idm:t.user.me openid");
this.options.put("SSLEnabled", "true");
this.options.put("redirectURL", "http://localhost:8080/callback");
this.options.put("logoutSufix", "/oauth2/v1/userlogout");
this.options.put(Constants.CONSOLE_LOG, "True");
this.options.put(Constants.LOG_LEVEL, "DEBUG");
return this.options;
}
다음은 이 SDK의 각 필수 속성에 대한 간략한 설명입니다.
이름 | 설명 |
---|---|
IDCSTokenAssertionConfiguration.IDCS_HOST |
Oracle Identity Cloud Service 인스턴스의 도메인 접미어입니다. |
IDCSTokenAssertionConfiguration.IDCS_PORT |
Oracle Identity Cloud Service 인스턴스용으로 예약된 HTTPS 포트 번호(일반적으로 443개)입니다. |
IDCSTokenAssertionConfiguration.IDCS_CLIENT_ID |
Identity Cloud Service 콘솔에 Java 웹 애플리케이션을 등록한 후 생성되는 클라이언트 ID 값입니다. |
IDCSTokenAssertionConfiguration.IDCS_CLIENT_SECRET |
Identity Cloud Service 콘솔에 Java 웹 애플리케이션을 등록한 후 생성되는 클라이언트 암호 값입니다. |
IDCSTokenAssertionConfiguration.IDCS_CLIENT_TENANT |
Oracle Identity Cloud Service 인스턴스의 도메인 접두어입니다. 이 접두어는 일반적으로 idcs-abcd1234 와 유사한 값입니다.
|
Constants.AUDIENCE_SERVICE_URL |
Oracle Identity Cloud Service 인스턴스의 정규화된 도메인 이름 URL입니다. |
Constants.TOKEN_ISSUER |
이 속성에 대해 Oracle은 https://identity.oraclecloud.com 값을 유지할 것을 권장합니다.
|
Constants.TOKEN_CLAIM_SCOPE |
범위는 애플리케이션이 Oracle Identity Cloud Service 사용자 대신 액세스하거나 처리할 수 있는 데이터를 제어합니다. 애플리케이션이 SDK를 사용하여 사용자를 인증하는 경우 범위는 |
SSLEnabled |
Oracle Identity Cloud Service가 HTTPS 또는 HTTP 요청에 응답하는지 여부를 나타냅니다. 이 속성에 대해 Oracle은 true 값을 유지할 것을 권장합니다.
|
Constants.CONSOLE_LOG |
SDK 로그를 사용으로 설정합니다. |
Constants.LOG_LEVEL |
SDK의 로그 레벨을 나타냅니다. |
응용 프로그램은 이러한 값을 하드 코딩하지 않도록 logoutSufix
및 redirectURL
속성을 모두 사용합니다. SDK는 필요하지 않습니다.
Java 웹 응용 프로그램은 /auth
URL을 매핑하는 AuthServlet
클래스를 구현합니다. 사용자가 Oracle Identity Cloud Service를 사용하여 인증하기로 결정하면 웹 브라우저에서 이 URL을 요청합니다. AuthServlet
클래스는 Authentication Manager
객체를 초기화하고, Java SDK를 사용하여 Oracle Identity Cloud Service의 권한 부여 코드 URL을 생성한 다음 웹 브라우저를 이 URL로 재지정합니다.
public class AuthServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Loading the configurations
Map<String, Object> options = new ConnectionOptions().getOptions();
//Configuration object instance with the parameters loaded.
IDCSTokenAssertionConfiguration config = new IDCSTokenAssertionConfiguration(options);
String redirectUrl = (String)options.get("redirectURL");
String scope = (String)options.get(Constants.TOKEN_CLAIM_SCOPE);
//Authentication Manager loaded with the configurations.
AuthenticationManager am = AuthenticationManagerFactory.getInstance(config);
//Using Authentication Manager to generate the Authorization Code URL, passing the
//application's callback URL as parameter, along with code value and code parameter.
String authzURL = am.getAuthorizationCodeUrl(redirectUrl, scope, "1234", "code");
//Redirecting the browser to the Oracle Identity Cloud Service Authorization URL.
response.sendRedirect(authzURL);
}
}
인증 코드 URL을 생성하는 데 사용되는 매개변수는 다음과 같습니다.
이름 | 설명 |
---|---|
redirectUrl |
사용자가 사인인한 후 Oracle Identity Cloud Service는 사용자의 웹 브라우저를 이 URL로 재지정합니다. 이 URL은 Identity Cloud Service 콘솔에서 신뢰할 수 있는 애플리케이션에 대해 구성할 URL과 일치해야 합니다. Java 웹 애플리케이션의 재지정 URL 지정에 대한 자세한 내용은 Java 애플리케이션 등록을 참조하십시오. |
scope |
인증의 OAuth 또는 OpenID Connect 범위입니다. 이 애플리케이션에는 openid 인증만 필요합니다.
|
state |
OAuth 프로토콜은 이 매개변수를 정의합니다. 샘플 Java 웹 애플리케이션은 이 코드를 사용하여 Oracle Identity Cloud Service에 대한 통신을 설정할 수 있는지 여부를 확인합니다. 이 예에서 이 매개변수의 값은 1234 입니다.
|
response_type |
승인 코드 부여 유형에 필요한 매개변수입니다. 이 예에서 이 매개변수의 값은 code 입니다.
|
사용자가 사인인한 후 Oracle Identity Cloud Service는 사용자의 웹 브라우저를 개발자가 구현해야 하는 콜백 URL로 재지정합니다. Java 웹 응용 프로그램은 CallbackServlet
를 사용하여 이 요청을 처리합니다.
public class CallbackServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Loading the configurations
Map<String, Object> options = new ConnectionOptions().getOptions();
//After Oracle Identity Cloud Service authenticates the user, the browser is redirected to the
//callback URL, implemented as a Servlet.
IDCSTokenAssertionConfiguration config = new IDCSTokenAssertionConfiguration(options);
//Authentication Manager loaded with the configurations.
AuthenticationManager am = AuthenticationManagerFactory.getInstance(config);
//Getting the authorization code from the "code" parameter
String authzCode = request.getParameter("code");
//Using the Authentication Manager to exchange the Authorization Code to an Access Token.
AuthenticationResult ar = am.authorizationCode(authzCode);
//Getting the Access Token object and its String value.
AccessToken access_token = ar.getToken(OAuthToken.TokenType.ACCESS_TOKEN);
String access_token_string = access_token.getToken();
//Getting the ID Token object and its String value.
IdToken id_token = ar.getToken(OAuthToken.TokenType.ID_TOKEN);
String id_token_string = id_token.getToken();
//Validating both Tokens to acquire information for User such as UserID,
//DisplayName, list of groups and AppRoles assigned to the user.
IdToken id_token_validated = am.validateIdToken(id_token_string);
//Storing information into the HTTP Session.
HttpSession session=request.getSession();
session.setAttribute("access_token", access_token_string);
session.setAttribute("id_token", id_token_string);
session.setAttribute("userId", id_token_validated.getUserId());
session.setAttribute("displayName", id_token_validated.getDisplayName());
//Forwarding the request to the Home page.
request.getRequestDispatcher("private/home.jsp").forward(request, response);
}
}
애플리케이션은 권한 부여 코드 매개변수를 요청하고 이를 사용하여 Java SDK의 AuthenticationManager.authorizationCode()
메소드를 호출하여 액세스 토큰과 ID 토큰을 모두 요청합니다. 그러면 서블릿이 AuthenticationManager
인스턴스를 사용하여 ID 토큰을 검증합니다. AuthenticationManager.validateIdToken()
메소드는 표시 이름, 사용자 ID, 사용자에게 지정된 그룹 및 애플리케이션 롤 목록과 같은 사용자 정보를 포함하는 IdToken
객체의 인스턴스를 반환합니다. 액세스 토큰 및 ID 토큰 값과 일부 사용자 정보는 모두 HTTP 세션 객체에 저장되므로 /private/home.jsp
이라는 응용 프로그램 내의 보호된 URL로 요청을 전달할 수 있습니다. /private/home.jsp
외에도 Java 웹 애플리케이션에는 보호된 다른 URL(/private/myProfile.jsp
)이 있습니다.
myProfile.jsp
페이지는 다음 코드 샘플을 사용하여 Oracle Identity Cloud Service에 사인인한 사용자에 대한 자세한 정보를 가져옵니다.
<%if(session.getAttribute("access_token")==null) response.sendRedirect("/login.html");%>
<!DOCTYPE html>
<%
/**
* The /private/myProfile.jsp page accesses the user's access token previously set in the session,
* calls the getAuthenticatedUser method to retrieve the user's information, and then formats it as HTML.
* @author felippe.oliveira@oracle.com
* @Copyright Oracle
*/
java.util.Map<String, Object> options = new sampleapp.util.ConnectionOptions().getOptions();
//Configuration object instance with the parameters loaded.
oracle.security.jps.idcsbinding.shared.IDCSTokenAssertionConfiguration configuration = new oracle.security.jps.idcsbinding.shared.IDCSTokenAssertionConfiguration(options);
oracle.security.jps.idcsbinding.shared.AuthenticationManager am = oracle.security.jps.idcsbinding.shared.AuthenticationManagerFactory.getInstance(configuration);
//Getting the Access Token and the Id Token from the session object
String access_token_string = (String)session.getAttribute("access_token");
String id_token_string = (String)session.getAttribute("id_token");
//Validating the ID Token to get user information, groups and app roles associated with the user.
oracle.security.jps.idcsbinding.api.AccessToken access_token_validated = am.validateAccessToken(access_token_string);
oracle.security.jps.idcsbinding.api.IdToken id_token_validated = am.validateIdToken(id_token_string);
%>
/private/myProfile.jsp
페이지는 세션에서 설정된 ID 토큰 값에 액세스하고, AuthenticationManager.validateIdToken()
메소드를 호출하여 사용자 정보를 검색한 다음 HTML 콘텐츠로 표시합니다.
<p><b>Information from the Identity Token:</b></p><p><%
out.println("DisplayName = "+ id_token_validated.getDisplayName() +"<br>");
out.println("IdentityDomain = "+ id_token_validated.getIdentityDomain() +"<br>");
out.println("UserName = "+ id_token_validated.getUserName()+"<br>");
out.println("UserId = "+ id_token_validated.getUserId()+"<br>");
out.println("Issuer = "+ id_token_validated.getIssuer()+"<br>");
java.util.List<oracle.security.jps.idcsbinding.api.IDCSAppRole> appRoles = id_token_validated.getAppRoles();
if(!appRoles.isEmpty()){
out.println("App Roles:<br>");
for(oracle.security.jps.idcsbinding.api.IDCSAppRole appRole: appRoles){
out.println(" appRole = "+ appRole.getName() +"<br>");
}//for
}//if
java.util.List<oracle.security.jps.idcsbinding.api.IDCSGroup> groups = id_token_validated.getGroupMembership();
if(!groups.isEmpty()){
out.println("Groups:<br>");
for(oracle.security.jps.idcsbinding.api.IDCSGroup group: groups){
out.println(" group = "+ group.getName() +"<br>");
}//for
}//if
%>
</p>
<p><b>Access Token:</b></p><p><%=access_token_string%></p>
애플리케이션과 Oracle Identity Cloud Service 간의 Single Sign-On에서 사용자를 사인아웃하기 위해 Java 웹 애플리케이션은 /logout
URL을 매핑하는 LogoutServlet
를 구현합니다.
public class LogoutServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session=request.getSession();
String id_token = (String)session.getAttribute("id_token");
session.invalidate();
Map options = new ConnectionOptions().getOptions();
String logoutURL = (String)options.get(Constants.AUDIENCE_SERVICE_URL) + (String)options.get("logoutSufix") +"?post_logout_redirect_uri=http%3A//localhost%3A8080&id_token_hint="+ id_token;
response.sendRedirect(logoutURL);
}
}
이 서블릿은 애플리케이션 세션을 무효화한 다음 사용자의 웹 브라우저를 Oracle Identity Cloud Service의 OAuth 로그아웃 URL로 재지정합니다.