瞭解Java應用程式與Oracle Identity Cloud Service之間的認證

您已準備好瞭解Java Web 應用程式與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 Web 應用程式會使用此存取記號,將存取權授予使用者應用程式中受保護的資源。三方流程使用授權代碼授權類型.

為了提高安全性,Oracle建議您使用三方流程來整合Java Web 應用程式與Oracle Identity Cloud Service以進行認證。透過使用授權代碼授權類型,您也可以存取Oracle Identity Cloud Service所保護的其他應用程式,而不需要重新驗證。

瞭解在Java應用程式使用 SDK 的主要使用案例

Java Web 應用程式實行兩個使用案例:一個用於驗證使用者,另一個用於存取登入使用者的詳細資訊。

下列資料流程圖表說明Web瀏覽器、Web應用程式以及每個使用案例之Oracle Identity Cloud Service 之間的事件、呼叫與回應流程。

使用案例# 1:認證使用者

資料流程的方式如下:

  1. 使用者要求受保護的資源。

  2. 認證模組使用 SDK 產生Oracle Identity Cloud Service的要求-授權程式碼 URL,並將此 URL 作為 Web 瀏覽器的重導回應傳送。

  3. Web 瀏覽器會呼叫 URL。

  4. 就會顯示Oracle Identity Cloud Service登入 頁面。

  5. 使用者送出Oracle Identity Cloud Service登入證明資料.

  6. 使用者登入之後,Oracle Identity Cloud Service會為使用者建立階段作業並發出授權代碼。

  7. Web 應用程式會呼叫後端 (或伺服器對伺服器) 來交換存取記號的授權代碼。

  8. Oracle Identity Cloud Service發出存取記號與 id 記號。

  9. 系統便會建立階段作業,並將使用者重導至「 頁」。

  10. Web 應用程式的「 頁」隨即顯示。

使用案例# 2:取得使用者的詳細資訊

資料流程的方式如下:

  1. 使用者要求/myProfile資源。

  2. Web 應用程式使用Oracle Identity Cloud Service的 SDK 來驗證 ID 記號。

  3. 從 Id 記號驗證傳回的資料以 JSON 物件的格式包含使用者的詳細資訊。

  4. 我的設定檔」頁面會將 JSON 物件轉換為 HTML 內容。

瞭解方法和函數

Java SDK 是您載入為 Web 應用程式庫的 JAR 檔案。此 JAR 檔案要求您同時必須載入到程式庫的這些第三方程式庫:

Java SDK 壓縮檔包含下列 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

  • 新增 JOSE + JWT 5.14

  • OAuth 2.0 SDK 與OpenID Connect擴充5.30

Oracle提供範例Java Web 應用程式,以示範如何使用Java SDK。此應用程式是使用 Servlet 技術建立的,可簡化學習體驗,以瞭解Java SDK 的運作方式。應用程式使用 Maven 取得所有程式庫並產生 Web 應用程式資源 (WAR) 檔案。

Java SDK 需要使用Oracle Identity Cloud Service連線資訊載入HashMap物件執行處理。Java Web 應用程式會在ConnectionOptions.java類別中實行此HashMap執行處理作為類別屬性。

//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 Web 應用程式後所產生的從屬端 ID 值。
IDCSTokenAssertionConfiguration.IDCS_CLIENT_SECRET 在Identity Cloud Service主控台中註冊Java Web 應用程式之後所產生的從屬端密碼值。
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 的日誌層次。

應用程式會同時使用logoutSufixredirectURL屬性,以避免產生這些值的強制程式碼。SDK 不需要。

Java Web 應用程式實行AuthServlet類別,對應/auth URL。當使用者決定使用Oracle Identity Cloud Service進行認證時,Web 瀏覽器會對此 URL 提出要求。AuthServlet類別會初始化Authentication Manager物件,使用Java SDK 產生Oracle Identity Cloud Service的授權程式碼 URL,然後將 Web 瀏覽器重導至此 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會將使用者的 Web 瀏覽器重導至此 URL。此 URL 必須符合您在Identity Cloud Service主控台中為信任應用程式設定的 URL。請參閱註冊Java應用程式,瞭解有關指定Java Web 應用程式之重導 URL 的詳細資訊。
scope 認證的OAuth或OpenID Connect範圍。此應用程式僅需要openid認證。
state OAuth協定定義此參數。範例Java Web 應用程式使用此代碼來檢查是否可以建立Oracle Identity Cloud Service通訊。在此範例中,此參數的值是1234
response_type 授權代碼授權類型所需的參數。在此範例中,此參數的值是code

使用者登入之後,Oracle Identity Cloud Service會將使用者的 Web 瀏覽器重導至開發人員必須實行的回呼 URL。Java Web 應用程式使用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 記號。然後 Servlet 會使用AuthenticationManager執行處理來驗證 ID 記號。AuthenticationManager.validateIdToken()方法會傳回IdToken物件的執行處理,其中包含使用者資訊,例如顯示名稱、使用者 id,以及指派給使用者的群組和應用程式角色清單。存取記號和 Id 記號值以及部分使用者資訊都儲存在 HTTP 階段作業物件中,因此要求可以轉送至名為/private/home.jsp之應用程式內的受保護 URL。除了/private/home.jsp之外,Java Web 應用程式還有另一個受保護的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之間單一登入的使用者,Java Web 應用程式會實行LogoutServlet,對應/logout URL:

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);
    }
}

此 Servlet 會讓應用程式的階段作業失效,然後將使用者的 Web 瀏覽器重導至Oracle Identity Cloud Service的OAuth登出 URL。