OAuth 2.0 服務呼叫

登錄的 OAuth 用戶端可以呼叫 WebSphere® Application Server OAuth 服務授權端點來要求存取記號。登錄的 OAuth 用戶端也可以呼叫 WebSphere Application Server OAuth 服務記號端點來要求存取記號。 之後,用戶端可以利用存取記號,從 WebSphere Application Server 要求受保護的 Web 資源。

WebSphere Application Server OAuth 2.0 服務支援下列流程。

授權碼流程

呼叫授權端點來要求授權碼。
OAuth 用戶端透過新增其用戶端 ID、用戶端密碼、狀態、重新導向 URI 及選用的範圍,將資源擁有者或使用者重新導向到「WebSphere Application Server OAuth 2.0 授權服務」。
https://host_name:port_number/oauth2/endpoint/provider_name/authorize
https://host_name:port_number/oauth2/declarativeEndpoint/provider_name/authorize
呼叫 OAuth 記號端點來要求存取記號。
OAuth 用戶端會將 authorization_code 授權類型、authorization coderedirect_urlclient_id 新增為要求參數,從而要求 WebSphere Application Server OAuth 2.0 記號端點中的存取記號。
https://host_name:port_number/oauth2/endpoint/provider_name/token
下列範例顯示使用授權碼時的 URI 建構,以及如何利用存取記號來存取 Web 資源:
String charset = "UTF-8";
String param1 = "code";

if (isAuthorizationCode){
  String query = String.format("response_type=%s&
                               client_id=%s&
                               client_secret=%s&
                               state=%s&
                               redirect_uri=%s&
                               scope=%s",
                               URLEncoder.encode(param1, charset),
                               URLEncoder.encode(clientId, charset),
                               URLEncoder.encode(clientSecret, charset),
                               URLEncoder.encode(state, charset),
                               URLEncoder.encode(redirectURI, charset),
                               URLEncoder.encode(scope, charset));
  String s = authorizationEndPoint + "?" + query;
  System.out.println("Visit: " + s + "\nand grant permission");
  System.out.print("Now enter the OAuth code you have received in redirect uri :");
  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  String code = br.readLine();
  param1 = "authorization_code";
  query = String.format("grant_type=%s&
                        code=%s&
                        client_id=%s&
                        client_secret=%s&
                        state=%s&
                        redirect_uri=%s&
                        scope=%s",
                        URLEncoder.encode(param1, charset),
                        URLEncoder.encode(code, charset),
                        URLEncoder.encode(clientId, charset),
                        URLEncoder.encode(clientSecret, charset),
                        URLEncoder.encode(state, charset),
                        URLEncoder.encode(redirectURI, charset),
                        URLEncoder.encode(scope, charset));
  URL url = new URL(tokenEndPoint);
  HttpsURLConnection con = (HttpsURLConnection)url. openConnection();
  con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset="  + charset);
  con.setDoOutput(true);
  con.setRequestMethod("POST");
  OutputStream output = null;
  try {
    output = con.getOutputStream();
    output.write(query.getBytes(charset));
    output.flush();
  } finally {
    if (output != null) try {
      output.close();
    } catch (IOException logOrIgnore) {}
  }
  con.connect();
  System.out.println("response message is = " + con.getResponseMessage());
  // 讀取伺服器的輸出
  BufferedReader reader = null;
  StringBuilder stringBuilder;
  reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
  stringBuilder = new StringBuilder();
  String line = null;
  try {
    while ((line = reader.readLine()) != null) {
      stringBuilder.append(line + "\n");
    }
  } finally {
    if (reader != null) try {
      reader.close();
    } catch (IOException logOrIgnore) {}
  }
  String tokenResponse = stringBuilder.toString();
  System.out.println ("response is = " + tokenResponse);
  JSONObject json = JSONObject.parse(tokenResponse);
  if (json.containsKey("access_token")) {
    accessToken = (String)json.get("access_token");
    this.accessToken = accessToken;
  }
  if (json.containsKey("refresh_token")) {
    refreshToken = (String)json.get("refresh_token");
  }
  //sendRequestForAccessToken(query);
  if (accessToken != null) {
    String query = String.format("access_token=%s",
                                 URLEncoder.encode(accessToken, charset));
    URL urlResource = new URL(resourceEndPoint);
    HttpsURLConnection conn = (HttpsURLConnection) urlResource.openConnection();
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-type", "application/x-www-form-urlencoded");
    conn.setDoOutput(true);
    output = null;
    try {
      output = conn.getOutputStream();
      output.write(query.getBytes(charset));
      output.flush();
    } finally {
      if (output != null) try {
        output.close();
      } catch (IOException logOrIgnore) {}
    }
    conn.connect();
    System.out.println("response to the resource request is = " + conn.getResponseMessage ());
    reader = null;
    if(conn.getResponseCode()>=200 && conn.getResponseCode() < 400) {
      reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
      stringBuilder = new StringBuilder();
      String line = null;
      try {
        while ((line = reader.readLine()) != null) {
          stringBuilder.append(line + "\n");
        }
      } finally {
        if (reader != null) try {
          reader.close();
        } catch (IOException  logOrIgnore) {}
      }
      System.out.println ("response message to the request resource is = " +  stringBuilder.toString());
    } else {
      isValidResponse = false;
    }
  }
}

隱含的授權流程

OAuth 用戶端會在要求參數中新增記號 response_typeredirect_urlclient_idscopestate,從而要求 WebSphere Application Server OAuth 2.0 授權端點中的存取記號。
https://host_name:port_number/oauth2/endpoint/provider_name/authorize
https://host_name:port_number/oauth2/declarativeEndpoint/provider_name/authorize
下列範例顯示使用隱含授權時的 URI 建構:
if (isImplicit) {
  param1 = "token";
  String query = String.format("response_type=%s&
                               client_id=%s&
                               state=%s&
                               redirect_uri=%s&
                               scope=%s",
                               URLEncoder.encode(param1, charset),
                               URLEncoder.encode(clientId, charset),
                               URLEncoder.encode(state, charset),
                               URLEncoder.encode(redirectURI, charset),
                               URLEncoder.encode(scope, charset));
  String s = authorizationEndPoint + "?" + query;
  System.out.println("Visit: " + s + "\nand grant permission");
  System.out.print("Now enter the access token you have received in redirect uri :");
  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  accessToken = br.readLine();
  if (accessToken != null) {
    // 利用存取記號來傳送「資源要求」
  }
}

用戶端認證流程

OAuth 用戶端會利用用戶端 ID 和用戶端密鑰來存取記號端點,且會針對存取記號加以交換,以供進行未來資源要求。在這個流程中,用戶端透過將 client_credentials 授權類型、client_idclient_secret 新增為要求參數來存取記號端點。
https://host_name:port_number/oauth2/endpoint/provider_name/token
下列範例顯示使用用戶端認證時的 URI 建構:
if (isClientCredentials){
  param1 = "client_credentials";
  String query = String.format("grant_type=%s&
                               scope=%s&
                               client_id=%s&
                               client_secret=%s",
                               URLEncoder.encode(param1, charset),
                               URLEncoder.encode(scope, charset),
                               URLEncoder.encode(clientId, charset),
                               URLEncoder.encode(clientSecret, charset));
  accessToken = sendRequestForAccessToken(query);
  if (accessToken != null) {
    //利用 (accessToken) 來傳送「資源要求」;
  }
}

資源擁有者密碼認證流程

「資源擁有者密碼認證」流程會將資源擁有者的使用者 ID 和密碼直接傳到記號端點。 在這個流程中,OAuth 用戶端會將 password 授權類型 client_idclient_secretusernamepasswordscopestate 新增為要求參數來存取記號端點。
https://host_name:port_number/oauth2/endpoint/provider_name/token
下列範例顯示使用資源擁有者密碼時的 URI 建構:
if (isResourceOwnerCredentials) {
  param1 = "password";
  String query = String.format("grant_type=%s&
                               username=%s&
                               password=%s&
                               scope=%s&
                               client_id=%s&
                               client_secret=%s",
                               URLEncoder.encode(param1, charset),
                               URLEncoder.encode(resOwnerName, charset),
                               URLEncoder.encode(resOwnerPassword, charset),
                               URLEncoder.encode(scope, charset),
                               URLEncoder.encode(clientId, charset),
                               URLEncoder.encode(clientSecret, charset));
  accessToken = sendRequestForAccessToken(query);
  if (accessToken != null) {
    //利用 (accessToken) 來傳送「資源要求」;
  }
}
如果存取記號過期,可以傳送重新整理記號來取得有效的存取記號。 下列範例顯示如何傳送重新整理記號:
if(isAccessToken) {
  if (this.accessToken != null) {
    if (!sendResourceRequest(this.accessToken)) {
      // 資源要求失敗...
      //取得重新整理記號
      param1 = "refresh_token";
      String query = String.format("grant_type=%s&
                                   client_id=%s&
                                   client_secret=%s&
                                   refresh_token=%s&
                                   scope=%s",
                                   URLEncoder.encode(param1, charset),
                                   URLEncoder.encode(clientId, charset),
                                   URLEncoder.encode(clientSecret, charset),
                                   URLEncoder.encode(this.refreshToken, charset),
                                   URLEncoder.encode(scope, charset));
      accessToken = sendRequestForAccessToken(query);
      if (accessToken != null) {
        sendResourceRequest(accessToken);
      }
    }
  }
}

指示主題類型的圖示 概念主題



「時間戳記」圖示 前次更新: 2016 年 11 月 30 日
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-libcore-mp&topic=cwlp_oauth_invoking
檔名:cwlp_oauth_invoking.html