Java 애플리케이션과 Oracle Identity Cloud Service 간 인증 정보 알아보기

Java 웹 애플리케이션과 Oracle Identity Cloud Service 간 인증에 대해 배울 준비가 되었습니다. 여기에는 다음이 포함됩니다.

  • Oracle Identity Cloud Service가 Java SDK에 대해 지원하는 규정된 인증 플로우

  • Java 애플리케이션과 함께 SDK를 사용하여 Oracle Identity Cloud Service 인증을 수행하는 경우 사용

  • Java SDK의 메소드 및 기능

위협 인증 플로우에 대해 알아보기

Oracle Identity Cloud Service는 Java SDK에 대해 규정된 인증 플로우를 지원합니다. 이 플로우에서 사용자는 Oracle Identity Cloud Service 직접 상호 작용합니다. 사용자가 사인인한 후 Oracle Identity Cloud Service SDK가 사용자 액세스 토큰에 대해 교환하는 권한 부여 코드를 발행합니다. Java 웹 응용 프로그램은 이 액세스 토큰을 사용하여 응용 프로그램의 보호된 리소스에 대한 액세스 권한을 사용자에게 부여합니다. 권한 부여 코드 권한 부여 유형을 사용하는 세 가지 플로우입니다.

보안 강화를 위해 Oracle 워크플로우를 사용하여 Java 웹 애플리케이션을 인증을 위한 Oracle Identity Cloud Service 과 통합하는 것이 좋습니다. 권한 부여 코드 권한 부여 유형을 사용하면 재인증 없이 Oracle Identity Cloud Service 로 보호되는 다른 애플리케이션에도 액세스할 수 있습니다.

Java 애플리케이션에서 SDK 사용에 대한 기본 사용 사례 학습

Java 웹 응용 프로그램은 사용자 인증에 사용되는 두 가지 사용 사례와 로그인한 사용자에 대한 세부 정보에 액세스하는 다른 사용 사례를 구현합니다.

다음 데이터 플로우 다이어그램은 각 사용 사례에 대해 웹 브라우저, 웹 애플리케이션, Oracle Identity Cloud Service 간의 이벤트, 호출 및 응답 플로우를 보여줍니다.

사용 사례 # 1: 사용자 인증

데이터 플로우는 다음과 같은 방식으로 발생합니다.

  1. 사용자가 보호된 리소스를 요청합니다.

  2. 인증 모듈은 SDK를 사용하여 Oracle Identity Cloud Service 요청 승인 코드 URL을 생성하고 이 URL을 웹 브라우저에 재지정 응답으로 보냅니다.

  3. 웹 브라우저가 URL을 호출합니다.

  4. [Oracle Identity Cloud Service 사인인 ] 페이지가 나타납니다.

  5. 사용자가 Oracle Identity Cloud Service 사인인 인증서를 제출합니다.

  6. 사용자가 사인인한 후 Oracle Identity Cloud Service 사용자가 세션을 생성하고 권한 부여 코드를 실행합니다.

  7. 웹 응용 프로그램은 백엔드(또는 서버간) 호출을 통해 액세스 토큰에 대한 권한 부여 코드를 교환합니다.

  8. Oracle Identity Cloud Service 접근 토큰 및 id 토큰을 발행합니다.

  9. 세션이 설정되고 사용자가 페이지로 재지정됩니다.

  10. 웹 응용 프로그램의 페이지가 나타납니다.

사용 사례 # 2: 사용자에 대한 세부정보 가져오기

데이터 플로우는 다음과 같은 방식으로 발생합니다.

  1. 사용자가 /myProfile 리소스를 요청합니다.

  2. 웹 애플리케이션은 Oracle Identity Cloud Service SDK를 사용하여 id 토큰을 검증합니다.

  3. Id 토큰 검증에서 반환된 데이터에 JSON 객체 형식의 사용자 세부정보가 포함되어 있습니다.

  4. [내 프로파일 ] 페이지는 JSON 객체를 HTML 콘텐츠로 렌더링합니다.

메소드 및 함수에 대해 알아보기

Java SDK는 웹 응용 프로그램 라이브러리로 로드하는 JAR 파일입니다. 이 JAR 파일에는 해당 타사 라이브러리도 라이브러리에 로드해야 합니다.

Java SDK zip 파일에는 SDK에 필요한 다음과 같은 필수 타사 라이브러리가 포함되어 있습니다. 애플리케이션에 로드할 수 있습니다.

  • ASM Helper Minidev 1.0.2

  • Apache Commons Collections 4.1

  • Apache Commons Lang 3.7

  • JSON 작은/빠른 구문 분석기 2.3

  • Nimbus LangTag 1.4.3

  • Nimbus JOSE + JWT 5.14

  • OAuth 2.0 SDK with OpenID Connect 확장 5.30

Oracle 은 샘플 Java 웹 애플리케이션을 제공하여 Java SDK를 사용하는 방법을 보여줍니다. 이 애플리케이션은 Servlet 기술로 구축되어 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를 사용하여 사용자를 인증하는 경우 범위는 openid 입니다. 응용 프로그램이 SDK를 사용하여 사용자에 대한 세부 정보를 가져오는 경우 범위는 urn:opc:idm:t.user.me openid 입니다.

SSLEnabled Oracle Identity Cloud Service 가 HTTPS 또는 HTTP 요청에 응답하는지 여부를 나타냅니다. 이 속성의 경우 Oracle 값을 true 로 유지하는 것이 좋습니다.
Constants.CONSOLE_LOG SDK 로그를 사용으로 설정합니다.
Constants.LOG_LEVEL SDK의 로그 레벨을 나타냅니다.

응용 프로그램은 logoutSufix 속성과 redirectURL 속성을 모두 사용하여 이러한 값의 하드 코드를 방지합니다. SDK에는 해당 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 접속 범위입니다. 이 애플리케이션에는 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 웹 애플리케이션에 다른 보호된 URLs: /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("&nbsp;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("&nbsp;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 's OAuth 로그아웃 URL로 재지정합니다.