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());
  // read the output from the server
  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) {
    // send Resource Request using the access token
  }
}

用戶端認證流程

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) {
    //send Resource Request using (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) {
    //send Resource Request using (accessToken);
  }
}
如果存取記號過期,可以傳送更新記號來取得有效的存取記號。 下列範例顯示如何傳送更新記號:
if(isAccessToken) {
  if (this.accessToken != null) {
    if (!sendResourceRequest(this.accessToken)) {
      // resource request failed...
      //get refresh token
      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);
      }
    }
  }
}

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

檔名:cwlp_oauth_invoking.html