2013-01-30

Force.com : REST API 開発 ユーザ名パスワード OAuth 認証


※ 更新履歴


  • 2013-03-01:  Authorize.java の JSON データの解析のところを JsonParser から JsonNode 使うように修正した
  • 2016-08-02:  Salesforce による TLS 1.0 の無効化 により、sandbox環境ではJava1.7で実行するとエラーがかえるようになり動かなくなる。javax.net.ssl.HttpsURLConnection 使えってよ



◇ 環境


  • Force.com: Developer Edition version 26.0: Winter'13
  • Java: 1.7.0_11
  • Jackson Java JSON-processor: Jackson-src-1.9.11



◆ ユーザ名パスワード OAuth 認証の仕様


詳細は Understanding the Username-Password OAuth Authentication Flow を参照

■ request body - parameter

□ url

https://login.salesforce.com/services/oauth2/token

□ parameter

パラメータ説明
grant_type「password」
client_idリモートアクセスアプリケーション定義の[コンシューマ鍵]
client_secretリモートアクセスアプリケーション定義の[コンシューマの秘密]
usernameユーザ名
passwordパスワード(セキュリティトークンを付加)

ex.)※ 実際は一行(改行なし)

grant_type=password
&client_id=3MVG9lKcPoNINVBIPJjdw1J9LLM82HnFVVX19KY1uA5mu0QqEWhqKpoW3svG3XHrXDiCQjK1mdgAvhCscA9GE
&client_secret=1955279925675241571
&username=testuser@salesforce.com
&password=mypasswordXXXXXXXXXX


■ response body

□ JSON 形式

パラメータ説明
idユーザ、およびユーザの詳細に関するクエリの両方を識別するために使用できる ID URL
issued_at署名作成日時(秒数)
instance_urlAPIコール送信先SFDCインスタンス
signatureコンシューマの非公開鍵で署名されている Base64 符号化されたHMAC-SHA256 署名
access_tokenアプリケーション要求用セッションIDとして機能するアクセストークン

ex.)※ 実際は一行(改行なし)

{
    "id":"https://login.salesforce.com/id/00Dx0000000BV7z/005x00000012Q9P",
    "issued_at":"1278448832702",
    "instance_url":"https://na1.salesforce.com",
    "signature":"0CmxinZir53Yex7nE0TD+zMpvIWYGb/bdJh6XfOH6EQ=",
    "access_token":"00Dx0000000BV7z!AR8AQAxo9UfVkh8AlV0Gomt9Czx9LjHnSSpwBMmbRcgKFmxOtvxjTrKW19ye6PE3Ds1eQz3z8jr3W7_VbWmEu4Q8TVGSTHxs"
}


■ 考慮事項

このフローではユーザがSalesforceでログインするためにリダイレクトされることはないため、ユーザは直接アプリケーションを認証できません。そのため、更新トークンは使用できません。アプリケーションで更新トークンが必要な場合、Web サーバまたはユーザエージェント OAuth フローの使用を検討してください。

... 考慮事項、何言っているのかよくわかっていない ;-(。



◆ ユーザ名パスワード OAuth 認証 with Java


■ Authorize.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;


public class Authorize {

    /** SFDC:コンシューマ鍵 */
    final static String CLIENT_ID = "(リモートアクセスアプリケーションのコンシューマ鍵)";
    /** SFDC:コンシューマの秘密 */
    final static String CLIENT_SECRET = "(リモートアクセスアプリケーションのコンシューマの秘密)";
    /** SFDC:コールバックURL */
    final static String RESIRECT_URI = "(リモートアクセスアプリケーションのコールバックURL)";
    /** SFDC:ユーザ名 */
    final static String USER_NAME = "(Force.com ユーザ名)";
    /** SFDC:パスワード */
    final static String PASSWORD = "(Force.com パスワード+セキュリティトークン)";    
    /** SFDC:トークン要求 */
    final static String ENVIRONMENT = "https://login.salesforce.com/services/oauth2/token";

    /** Id URL */
    public String id;
    /** 署名作成日時(秒数) */
    public String issued_at;
    /** インスタンスURL */
    public String instance_url;
    /** HMAC-SHA256 署名 */
    public String signature;
    /** アクセストークン */
    public String access_token;

    /**
     * 実行
     * @throws IOException
     */
    public void execute() throws IOException {

        // 接続
        URL url = new URL(ENVIRONMENT);
        HttpURLConnection conn = (HttpURLConnection)url.openConnection();
        conn.setRequestMethod("POST");
        conn.setDoOutput(true);
        conn.setInstanceFollowRedirects(false);
        conn.setRequestProperty("Accept-Language", "ja");    

        // request body 作成
        Map<String, String> params = new HashMap<String, String>();
        params.put("grant_type", "password");
        params.put("client_id", CLIENT_ID);
        params.put("client_secret", CLIENT_SECRET);
        params.put("username", USER_NAME);
        params.put("password", PASSWORD);
        StringBuilder sb = new StringBuilder();
        for(Iterator<Map.Entry<String, String>> i=params.entrySet().iterator(); i.hasNext(); ) {
            Map.Entry<String, String> entry = i.next();
            String key = entry.getKey();
            String val = entry.getValue();
            sb.append(key).append("=").append(val).append("&");
        }
        if(sb.toString().endsWith("&")) {
            sb = sb.deleteCharAt(sb.length()-1);
        }
        String sParams = sb.toString();

        System.out.println(sParams);

        // request body 送信
        PrintWriter writer;
        writer = new PrintWriter(conn.getOutputStream());
        writer.print(sParams);
        writer.close();

        // response body(json データ)の解析
        StringBuilder json = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String line;
        while ((line = reader.readLine()) != null) {
            json.append(line);
        }
        reader.close();
        String jsonText = json.toString();

        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = mapper.readValue(jsonText, JsonNode.class);

        this.id = root.get("id").getTextValue();
        this.issued_at = root.get("issued_at").getTextValue();
        this.instance_url = root.get("instance_url").getTextValue();
        this.signature = root.get("signature").getTextValue();
        this.access_token = root.get("access_token").getTextValue();


        // 切断
        conn.disconnect();
    }
}

コールバック URL にて実行する

// ユーザ名パスワード OAuth 認証
Authorize authorize = new Authorize();
authorize.execute();

これで、アクセストークン取得できた!
が、考慮事項が気になりはじめた今日この頃



◇ 参考





0 件のコメント:

コメントを投稿