AuthProviderPluginClass クラス
名前空間
使用方法
シングルサインオン用のカスタム認証プロバイダーを作成するには、Auth.AuthProviderPluginClass を拡張するクラスを作成します。このクラスにより、認証プロバイダーのカスタム設定を保存し、ユーザーが外部サービスプロバイダーのログイン情報を使用して Salesforce にログインしたときに認証プロトコルを処理できます。Salesforce で、このインターフェースを実装するクラスは、[設定] の [認証プロバイダー] にある [プロバイダータイプ] ドロップダウンリストに表示されます。クラスを実行するよう指定するユーザーに「アプリケーションのカスタマイズ」権限と「認証プロバイダーの管理」権限があることを確認します。
API バージョン 39.0 以降、カスタムの外部認証プロバイダーを作成するには抽象クラス AuthProviderPluginClass を使用します。このクラスは AuthProviderPlugin インターフェースを置き換えます。インターフェースを使用してカスタム認証プロバイダープラグインをすでに実装している場合、その認証プロバイダーは引き続き機能します。ただし、プラグインを拡張するには AuthProviderPluginClass を使用してください。インターフェースを作成していない場合は、この抽象クラ���を拡張してカスタム認証プロバイダープラグインを作成します。設定は、「AuthProviderPluginClass コード例」を参照してください。
AuthProviderPluginClass のメソッド
AuthProviderPluginClass メソッドでは、DML オプションはサポートされません。
getCustomMetadataType()
署名
public String getCustomMetadataType()
使用方法
getCustomMetatadaType() メソッドは、カスタムメタデータ型の名前のみを返します。カスタムメタデータレコード名は返しません。API バージョン 39.0 以降、Auth.AuthProviderPluginClass を拡張してカスタムの外部認証プロバイダーを作成する場合はこのメソッドを使用します。
getUserInfo(authProviderConfiguration, response)
署名
public Auth.UserData getUserInfo(Map<String,String> authProviderConfiguration, Auth.AuthProviderTokenResponse response)
パラメーター
- authProviderConfiguration
- 型: Map<String, String>
- カスタム認証プロバイダーの設定。Salesforce にカスタムメタデータ型を作成すると、設定でカスタムメタデータ型のデフォルト値が入力されます。または、[設定] の [承認プロバイダー] でカスタムプロバイダーを作成したときに入力した値を設定で指定することもできます。
- response
- 型: Auth.AuthProviderTokenResponse
-
OAuth アクセストークン、OAuth の秘密または更新トークン、および現在のユーザーを認証するために認証プロバイダーによって指定された状態。
使用方法
API バージョン 39.0 以降、Auth.AuthProviderPluginClass を拡張してカスタム認証プロバイダーを作成する場合はこのメソッドを使用します。
1HttpRequest req = new HttpRequest();
2String url = 'https://login.salesforce.com/';
3req.setEndpoint(url);
4req.setMethod('GET');
5Http http = new Http();
6HTTPResponse res = http.send(req);handleCallback(authProviderConfiguration, callbackState)
署名
public Auth.AuthProviderTokenResponse handleCallback(Map<String,String> authProviderConfiguration, Auth.AuthProviderCallbackState callbackState)
パラメーター
- authProviderConfiguration
- 型: Map<StringString>
- カスタム認証プロバイダーの設定。Salesforce にカスタムメタデータ型を作成すると、設定にカスタムメタデータ型のデフォルト値が入力されます。または、[設定] の [承認プロバイダー] でカスタムプロバイダーを作成したときに入力した値を設定で指定することもできます。
- callbackState
- 型: Auth.AuthProviderCallbackState
- 認証要求の HTTP ヘッダー、本文、および queryParams が含まれるクラス。
使用方法
API バージョン 39.0 以降、Auth.AuthProviderPluginClass を拡張してカスタム認証プロバイダーを作成する場合はこのメソッドを使用します。
initiate(authProviderConfiguration, stateToPropagate)
署名
public System.PageReference initiate(Map<String,String> authProviderConfiguration, String stateToPropagate)
パラメーター
使用方法
API バージョン 39.0 以降、Auth.AuthProviderPluginClass を拡張してカスタム認証プロバイダーを作成する場合はこのメソッドを使用します。
refresh(authProviderConfiguration, refreshToken)
署名
public Auth.OAuthRefreshResult refresh(Map<String,String> authProviderConfiguration, String refreshToken)
パラメーター
戻り値
型: Auth.OAuthRefreshResult
新しいアクセストークンを返すか、エラーが発生した場合はエラーメッセージを返します。
使用方法
要求が成功した場合、アクセストークンおよび更新トークンと共に Auth.OAuthRefreshResult を応答に返します。エラーを受け取った場合は、エラーメッセージにエラー文字列を必ず設定してください。NULL のエラー文字列はエラーがないことを示します。
この更新方法は指定ログイン情報でのみ機能します。標準の OAuth 更新フローに従いません。指定ログイン情報を使用する更新方法は、前の要求で 401 が返された場合にのみ機能します。
AuthProviderPluginClass コード例
次の例は、抽象クラス Auth.AuthProviderPluginClass を使用してカスタムの認証プロバイダープラグインを実装する方法を示しています。
1global class Concur extends Auth.AuthProviderPluginClass {
2
3 // Use this URL for the endpoint that the
4 // authentication provider calls back to for configuration.
5 public String redirectUrl;
6 private String key;
7 private String secret;
8
9 // Application redirection to the Concur website for
10 // authentication and authorization.
11 private String authUrl;
12
13 // URI to get the new access token from concur using the GET verb.
14 private String accessTokenUrl;
15
16 // Api name for the custom metadata type created for this auth provider.
17 private String customMetadataTypeApiName;
18
19 // Api URL to access the user in Concur
20 private String userAPIUrl;
21
22 // Version of the user api URL to access data from Concur
23 private String userAPIVersionUrl;
24
25 global String getCustomMetadataType() {
26 return customMetadataTypeApiName;
27 }
28
29 global PageReference initiate(Map<string,string>
30 authProviderConfiguration, String stateToPropagate)
31 {
32 authUrl = authProviderConfiguration.get('Auth_Url__c');
33 key = authProviderConfiguration.get('Key__c');
34
35 // Here the developer can build up a request of some sort.
36 // Ultimately, they return a URL where we will redirect the user.
37 String url = authUrl + '?client_id='+ key +'&scope=USER,EXPRPT,LIST&redirect_uri='+ redirectUrl + '&state=' + stateToPropagate;
38 return new PageReference(url);
39 }
40
41 global Auth.AuthProviderTokenResponse handleCallback(Map<string,string>
42 authProviderConfiguration, Auth.AuthProviderCallbackState state )
43 {
44 // Here, the developer will get the callback with actual protocol.
45 // Their responsibility is to return a new object called
46 // AuthProviderTokenResponse.
47 // This will contain an optional accessToken and refreshToken
48 key = authProviderConfiguration.get('Key__c');
49 secret = authProviderConfiguration.get('Secret__c');
50 accessTokenUrl = authProviderConfiguration.get('Access_Token_Url__c');
51
52 Map<String,String> queryParams = state.queryParameters;
53 String code = queryParams.get('code');
54 String sfdcState = queryParams.get('state');
55
56 HttpRequest req = new HttpRequest();
57 String url = accessTokenUrl+'?code=' + code + '&client_id=' + key +
58 '&client_secret=' + secret;
59 req.setEndpoint(url);
60 req.setHeader('Content-Type','application/xml');
61 req.setMethod('GET');
62
63 Http http = new Http();
64 HTTPResponse res = http.send(req);
65 String responseBody = res.getBody();
66 String token = getTokenValueFromResponse(responseBody, 'Token', null);
67
68 return new Auth.AuthProviderTokenResponse('Concur', token,
69 'refreshToken', sfdcState);
70 }
71
72 global Auth.UserData getUserInfo(Map<string,string>
73 authProviderConfiguration,
74 Auth.AuthProviderTokenResponse response)
75 {
76 //Here the developer is responsible for constructing an
77 //Auth.UserData object
78 String token = response.oauthToken;
79 HttpRequest req = new HttpRequest();
80 userAPIUrl = authProviderConfiguration.get('API_User_Url__c');
81 userAPIVersionUrl = authProviderConfiguration.get
82 ('API_User_Version_Url__c');
83 req.setHeader('Authorization', 'OAuth ' + token);
84 req.setEndpoint(userAPIUrl);
85 req.setHeader('Content-Type','application/xml');
86 req.setMethod('GET');
87
88 Http http = new Http();
89 HTTPResponse res = http.send(req);
90 String responseBody = res.getBody();
91 String id = getTokenValueFromResponse(responseBody,
92 'LoginId',userAPIVersionUrl);
93 String fname = getTokenValueFromResponse(responseBody,
94 'FirstName', userAPIVersionUrl);
95 String lname = getTokenValueFromResponse(responseBody,
96 'LastName', userAPIVersionUrl);
97 String flname = fname + ' ' + lname;
98 String uname = getTokenValueFromResponse(responseBody,
99 'EmailAddress', userAPIVersionUrl);
100 String locale = getTokenValueFromResponse(responseBody,
101 'LocaleName', userAPIVersionUrl);
102 Map<String,String> provMap = new Map<String,String>();
103 provMap.put('what1', 'noidea1');
104 provMap.put('what2', 'noidea2');
105 return new Auth.UserData(id, fname, lname, flname,
106 uname, 'what', locale, null, 'Concur', null, provMap);
107 }
108
109 private String getTokenValueFromResponse(String response,
110 String token, String ns)
111 {
112 Dom.Document docx = new Dom.Document();
113 docx.load(response);
114 String ret = null;
115
116 dom.XmlNode xroot = docx.getrootelement() ;
117 if(xroot != null){ ret = xroot.getChildElement(token, ns).getText();
118 }
119 return ret;
120 }
121
122 }サンプルテストクラス
次の例には、Concur のテストクラスが含まれています。
1@IsTest
2 public class ConcurTestClass {
3
4 private static final String OAUTH_TOKEN = 'testToken';
5 private static final String STATE = 'mocktestState';
6 private static final String REFRESH_TOKEN = 'refreshToken';
7 private static final String LOGIN_ID = 'testLoginId';
8 private static final String USERNAME = 'testUsername';
9 private static final String FIRST_NAME = 'testFirstName';
10 private static final String LAST_NAME = 'testLastName';
11 private static final String EMAIL_ADDRESS = 'testEmailAddress';
12 private static final String LOCALE_NAME = 'testLocalName';
13 private static final String FULL_NAME = FIRST_NAME + ' ' + LAST_NAME;
14 private static final String PROVIDER = 'Concur';
15 private static final String REDIRECT_URL =
16 'http://localhost/services/authcallback/orgId/Concur';
17 private static final String KEY = 'testKey';
18 private static final String SECRET = 'testSecret';
19 private static final String STATE_TO_PROPOGATE = 'testState';
20 private static final String ACCESS_TOKEN_URL =
21 'http://www.dummyhost.com/accessTokenUri';
22 private static final String API_USER_VERSION_URL =
23 'http://www.dummyhost.com/user/20/1';
24 private static final String AUTH_URL =
25 'http://www.dummy.com/authurl';
26 private static final String API_USER_URL =
27 'www.concursolutions.com/user/api';
28
29 // In the real world scenario, the key and value would be read
30 // from the (custom fields in) custom metadata type record.
31 private static Map<String,String> setupAuthProviderConfig ()
32 {
33 Map<String,String> authProviderConfiguration = new Map<String,String>();
34 authProviderConfiguration.put('Key__c', KEY);
35 authProviderConfiguration.put('Auth_Url__c', AUTH_URL);
36 authProviderConfiguration.put('Secret__c', SECRET);
37 authProviderConfiguration.put('Access_Token_Url__c', ACCESS_TOKEN_URL);
38 authProviderConfiguration.put('API_User_Url__c',API_USER_URL);
39 authProviderConfiguration.put('API_User_Version_Url__c',
40 API_USER_VERSION_URL);
41 authProviderConfiguration.put('Redirect_Url__c',REDIRECT_URL);
42 return authProviderConfiguration;
43
44 }
45
46 static testMethod void testInitiateMethod()
47 {
48 String stateToPropogate = 'mocktestState';
49 Map<String,String> authProviderConfiguration = setupAuthProviderConfig();
50 Concur concurCls = new Concur();
51 concurCls.redirectUrl = authProviderConfiguration.get('Redirect_Url__c');
52 PageReference expectedUrl = new PageReference(authProviderConfiguration.get('Auth_Url__c') + '?client_id='+
53 authProviderConfiguration.get('Key__c') +'&scope=USER,EXPRPT,LIST&redirect_uri='+
54 authProviderConfiguration.get('Redirect_Url__c') + '&state=' +
55 STATE_TO_PROPOGATE);
56 PageReference actualUrl = concurCls.initiate(authProviderConfiguration, STATE_TO_PROPOGATE);
57 System.assertEquals(expectedUrl.getUrl(), actualUrl.getUrl());
58 }
59
60 static testMethod void testHandleCallback()
61 {
62 Map<String,String> authProviderConfiguration =
63 setupAuthProviderConfig();
64 Concur concurCls = new Concur();
65 concurCls.redirectUrl = authProviderConfiguration.get
66 ('Redirect_Url_c');
67
68 Test.setMock(HttpCalloutMock.class, new
69 ConcurMockHttpResponseGenerator());
70
71 Map<String,String> queryParams = new Map<String,String>();
72 queryParams.put('code','code');
73 queryParams.put('state',authProviderConfiguration.get('State_c'));
74 Auth.AuthProviderCallbackState cbState =
75 new Auth.AuthProviderCallbackState(null,null,queryParams);
76 Auth.AuthProviderTokenResponse actualAuthProvResponse =
77 concurCls.handleCallback(authProviderConfiguration, cbState);
78 Auth.AuthProviderTokenResponse expectedAuthProvResponse =
79 new Auth.AuthProviderTokenResponse(
80 'Concur', OAUTH_TOKEN, REFRESH_TOKEN, null);
81
82 System.assertEquals(expectedAuthProvResponse.provider,
83 actualAuthProvResponse.provider);
84 System.assertEquals(expectedAuthProvResponse.oauthToken,
85 actualAuthProvResponse.oauthToken);
86 System.assertEquals(expectedAuthProvResponse.oauthSecretOrRefreshToken,
87 actualAuthProvResponse.oauthSecretOrRefreshToken);
88 System.assertEquals(expectedAuthProvResponse.state,
89 actualAuthProvResponse.state);
90
91 }
92
93 static testMethod void testGetUserInfo()
94 {
95 Map<String,String> authProviderConfiguration =
96 setupAuthProviderConfig();
97 Concur concurCls = new Concur();
98
99 Test.setMock(HttpCalloutMock.class, new
100 ConcurMockHttpResponseGenerator());
101
102 Auth.AuthProviderTokenResponse response =
103 new Auth.AuthProviderTokenResponse(
104 PROVIDER, OAUTH_TOKEN ,'sampleOauthSecret', STATE);
105 Auth.UserData actualUserData = concurCls.getUserInfo(
106 authProviderConfiguration, response) ;
107
108 Map<String,String> provMap = new Map<String,String>();
109 provMap.put('key1', 'value1');
110 provMap.put('key2', 'value2');
111
112 Auth.UserData expectedUserData = new Auth.UserData(LOGIN_ID,
113 FIRST_NAME, LAST_NAME, FULL_NAME, EMAIL_ADDRESS,
114 null, LOCALE_NAME, null, PROVIDER, null, provMap);
115
116 System.assertNotEquals(expectedUserData,null);
117 System.assertEquals(expectedUserData.firstName,
118 actualUserData.firstName);
119 System.assertEquals(expectedUserData.lastName,
120 actualUserData.lastName);
121 System.assertEquals(expectedUserData.fullName,
122 actualUserData.fullName);
123 System.assertEquals(expectedUserData.email,
124 actualUserData.email);
125 System.assertEquals(expectedUserData.username,
126 actualUserData.username);
127 System.assertEquals(expectedUserData.locale,
128 actualUserData.locale);
129 System.assertEquals(expectedUserData.provider,
130 actualUserData.provider);
131 System.assertEquals(expectedUserData.siteLoginUrl,
132 actualUserData.siteLoginUrl);
133 }
134
135
136 // Implement a mock http response generator for Concur.
137 public class ConcurMockHttpResponseGenerator implements HttpCalloutMock
138 {
139 public HTTPResponse respond(HTTPRequest req)
140 {
141 String namespace = API_USER_VERSION_URL;
142 String prefix = 'mockPrefix';
143
144 Dom.Document doc = new Dom.Document();
145 Dom.XmlNode xmlNode = doc.createRootElement(
146 'mockRootNodeName', namespace, prefix);
147 xmlNode.addChildElement('LoginId', namespace, prefix)
148 .addTextNode(LOGIN_ID);
149 xmlNode.addChildElement('FirstName', namespace, prefix)
150 .addTextNode(FIRST_NAME);
151 xmlNode.addChildElement('LastName', namespace, prefix)
152 .addTextNode(LAST_NAME);
153 xmlNode.addChildElement('EmailAddress', namespace, prefix)
154 .addTextNode(EMAIL_ADDRESS);
155 xmlNode.addChildElement('LocaleName', namespace, prefix)
156 .addTextNode(LOCALE_NAME);
157 xmlNode.addChildElement('Token', null, null)
158 .addTextNode(OAUTH_TOKEN);
159 System.debug(doc.toXmlString());
160 // Create a fake response
161 HttpResponse res = new HttpResponse();
162 res.setHeader('Content-Type', 'application/xml');
163 res.setBody(doc.toXmlString());
164 res.setStatusCode(200);
165 return res;
166 }
167
168 }
169 }