SalesforceにおけるOAuth2.0/OpenID Connect

SalesforceにおけるOAuth2.0/OpenID Connect

概要

本記事では、業界標準であるOAuth2.0とOpenID Connectの概要を紹介した後に、Salesforceではそれらをどのように実装することができるのかを簡単に記載していきたいと思います。

本記事のベースとなるOAuth2.0やOpenID Connectの技術的な事項はこちらの本で学習しました。クライアント、認可サーバー、保護対象リソースのそれぞれについてサンプルのソースコードでどのように動作するかが詳細に記載されており理解するのに非常に役に立ちました。おすすめです。

認証・認可とは

それぞれ詳細を説明すると非常に長くなるのですが、あえて一言で言うと下記で表せます。

認証

通信の相手が誰(何)であるかを確認すること

認可

とある特定の条件に対して、リソースアクセスの権限を与えること

Salesforceにおける認証・認可とは

Salesforceで実現可能な認証・認可の仕組みは下記が上げられます。

#名称概要機能名
1フォーム認証Webブラウザでユーザ名とパスワードを入力する
最も基本的な認証方式
標準ログイン画面
22要素認証認証に2つ目の要素を追加することでセキュリティを強化するSalesforce Authenticator
3SSO一回の認証で複数のサービスを利用できる仕組み
Salesforceは、IdpとSPのどちらになることもできる
SAMLシングルサインオン
4証明書認証PCもしくはモバイルデバイスに配布されたクライアント証明書でログイン認証を行う証明書認証
5OAuth/OpenID Connect ←本記事ではこれを解説外部アプリケーションにSalesforceのデータへのアクセスする際にその認可を与える仕組み接続アプリケーション
6Social Sign onソーシャルアカウントで認証を行う認証プロバイダ
7代理認証ユーザの認証を外部サービスで行う
外部サービスはSalesforceが指定するWSDLに合わせたインターフェースを実装する必要がある
代理認証

OAuth2.0とは

概要

OAuth2.0は、業界標準でありRFCに下記のように定義されております。RFC6794(The OAuth 2.0 Authorization Framework)
https://tools.ietf.org/html/rfc6749

‘OAuth 2.0 は, サードパーティーアプリケーションによるHTTPサービスへの限定的なアクセスを可能にする認可フレームワークである. サードパーティーアプリケーションによるアクセス権の取得には, リソースオーナーとHTTPサービスの間で同意のためのインタラクションを伴う場合もあるが, サードパーティーアプリケーション自身が自らの権限においてアクセスを許可する場合もある. 本仕様書はRFC 5849に記載されているOAuth 1.0 プロトコルを廃止し, その代替となるものである.’

言い換えると、下記のように表せます。

  • リソース所有者の代わりとして対象のリソースへのアクセスを許可するための手段
  • サード・パーティー製のアプリケーションがHTTPサービスへの制限されたアクセス権を取得できるするようにするためのもの
  • OAuthとはシステムを構成しているある要素から別の構成要素にアクセス権を渡すためのもの

では、なんのためにOAuthを使用して認可をするかというと

  • サード・パーティ製のアプリケーションにユーザーの ID & パスワードを渡さない

となります。

概要イメージ

0. まずユーザであるリソース所有者がクライアントのアプリケーションを使用します。
1. クライアントは、保護対象リソースへアクセスするために一旦認可サーバーへリクエストを行います。
2. 認可サーバーはリソース所有者との間でユーザ認証および認可を行います。
3. 認可サーバーはユーザとの認証・認可が完了しているので、クライアントへアクセストークンを返却します。
4. クライアントは、保護対象リソースへアクセストークンを利用してAPIアクセスを行います。

各構成要素

  • クライアント ・・・ ソフトウェアであり、リソース所有者の代わりとして保護対象リソースへのアクセスを行うもの
  • 認可サーバー ・・・ OAuthの仕組みの中心的な役割を担うHTTPサーバーのこと. リソース所有者にクライアントを認可するための仕組みを提供し、トークンをクライアントに発行するもの
  • リソース所有者 ・・・ クライアントにアクセス権を委譲する権限を持つ存在. ソフトウェアでなくユーザー.
  • 保護対象リソース ・・・ HTTPサーバーから提供されており、そのリソースにアクセスするにはOAuthのトークンが必要となる. 保護対象リソースは提示されたトークンを検証して、リクエストに応えるかを判定する
  • アクセストークン ・・・ 認可サーバーによってクライアントへ発行され、クライアントに権限が委譲されたことを示すもの
  • スコープ ・・・ 保護対象リソースでの権限を表すものであり、クライアントに付与されるアクセス権限を制限するための仕組み
  • リフレッシュトークン ・・・ 新しいアクセストークンを発行するために使用する

認可コードフロー(Authrorization Code Grant Type)

OAuthのいくつかあるフローの中で最も標準的なフローである認可コードフローは下記のようになります。

認可リクエスト/認可レスポンスのイメージ

  • response_type=codeで認可コードフローを指定
  • codeの値が発行された認可コード

トークンリクエスト/トークンレスポンスのイメージ

  • grant_type ・・・ authorization_codeで認可コードフローを指定。

その他のフロー

#フロー名概要
1認可コードフロー
(Authorization Code Type)
最も標準系のフロー。
クライアントが認可コードを経由してアクセストークンを取得する。
2インプリシットフロー
(Implicit Grant Type)
JavaScriptアプリケーション等で完全にブラウザ内で動作している場合に使用する。
クライアントは認可エンドポイントから直接アクセストークンを取得する。
3クライアント・クレデンシャルフロー
(Client Credentials Grant Type)
ユーザに関係なくクライアントアプリへ直接アクセストークンを発行する。
4リソースオーナー・パスワード・クレデンシャルズフロー
(Resource Owner Password Credentials Grant Type)
基本的に非推奨。(アンチパターン)
アプリケーション側でID、PWを入力させて、それをトークンエンドポイントへ送り直接アクセストークンを取得する。
5リフレッシュトークンフロー
(Refresh Token Grant Type)
リフレッシュトークンを使用して、アクセストークンの再発行を行う。

OpenID Connectとは

概要

OpenID Connect Core1.0
https://openid.net/connect/

OpenID Connect 1.0 は, OAuth 2.0 プロトコルの上にシンプルなアイデンティティレイヤーを付与したものである. このプロトコルは Client が Authorization Server の認証結果に基づいて End-User のアイデンティティを検証可能にする. また同時に End-User の必要最低限のプロフィール情報を, 相互運用可能かつ RESTful な形で取得することも可能にする.

これらをわかりやすく言い換えると下記のように表せます。

  • OAuth 2.0 + Identity Layer = OpenID Connect
  • Identity Layer = ID Token + UserInfo API
  • ID Token ・・・ APIプロバイダー側のUser情報が取得できること
  • UserInfo API ・・・ APIプロバイダー側のプロフィール情報を取得できる

では、なんのためにOpenID Connectを使うかというと

  • クライアントがユーザの認証情報を取得するため

となります。

フロー

IDトークンとは

一言で言うと

認証結果として得られるトークン

です。

サンプルですが、実際の文字列は下記のようなものになります。

eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAibmFtZSI6ICJKYW5lIERvZSIsCiAiZ2l2ZW5fbmFtZSI6ICJKYW5lIiwKICJmYW1pbHlfbmFtZSI6ICJEb2UiLAogImdlbmRlciI6ICJmZW1hbGUiLAogImJpcnRoZGF0ZSI6ICIwMDAwLTEwLTMxIiwKICJlbWFpbCI6ICJqYW5lZG9lQGV4YW1wbGUuY29tIiwKICJwaWN0dXJlIjogImh0dHA6Ly9leGFtcGxlLmNvbS9qYW5lZG9lL21lLmpwZyIKfQ.rHQjEmBqn9Jre0OLykYNnspA10Qql2rvx4FsD00jwlB0Sym4NzpgvPKsDjn_wMkHxcp6CilPcoKrWHcipR2iAjzLvDNAReF97zoJqq880ZD1bwY82JDauCXELVR9O6_B0w3KE7yM2macAAgNCUwtik6SjoSUZRcfO5lygIyLENx882p6MtmwaL1hd6qn5RZOQ0TLrOYu0532g9ExxcmChymrB4xLykpDj3lUivJt63eEGGN6DH5K6o33TcxkIjNrCD4XB1CKKumZvCedgHHF3IAK4dVEDSUoGlH9z4pP_eWYNXvqQOjGs-rDaQzUHl 6cQQWNiDpWOl_lxXjQEvQ

これは以下のようにピリオド区切りの構成(JWS形式)となっています。
ヘッダー.ペイロード(本文).署名
それぞれは、base64urlでエンコードされているのでデコードすると下記のようになります。

[ペイロード]
{ “iss”: “http://server.example.com”,
“sub”: “248289761001”,
“aud”: “s6BhdRkqt3”,
 “nonce”: “n-0S6_WzA2Mj”,
 “exp”: 1311281970,
“iat”: 1311280970,
“name”: “Jane Doe”,
“given_name”: “Jane”,
“family_name”: “Doe”,
“gender”: “female”,
“birthdate”: “0000-10-31”,
“email”: “janedoe@example.com”,
“picture”:”http://example.com/janedoe/me.jpg” }

SalesforceにおけるOAuth2.0/OpenID Connectとは

概要

OAuth2.0の認可サーバーとOpenIDプロバイダーにあたる部分がSalesforceでは接続アプリケーションによって簡単に作成することができます。

エンドポイント

接続アプリケーションを定義してあとはクライアントアプリケーションが呼び出すエンドポイントは下記のようになります。

#エンドポイント概要
1https://login.salesforce.com/services/oauth2/authorizeSalesforceの認証エンドポイント
2https://login.salesforce.com/services/oauth2/successredirect_uri パラメータで指定されたコールバック URL
接続アプリケーションにも設定
※ リフレッシュトークンを取得する場合には、SalesforceのURIにする必要がある
3https://login.salesforce.com/services/oauth2/introspectSalesforceのトークンイントロスペクションエンドポイント
 ※ アクセストークンが有効かを確認
4https://login.salesforce.com/services/oauth2/tokenSalesforceのトークン要求エンドポイント
5https://login.salesforce.com/services/oauth2/revokeSalesforceのトークン取り消しエンドポイント

Salesforceでのフロー名とのマッピング

#フロー名Salesforce
1認可コードフロー
(Authorization Code Type)
Webサーバーフロー
2インプリシットフロー
(Implicit Grant Type)
ユーザエージェントフロー
3リソースオーナー・パスワード・クレデンシャルズフロー
(Resource Owner Password Credentials Grant Type)
ユーザ名パスワードフロー
4クライアント・クレデンシャルフロー
(Client Credentials Grant Type)
JWTベアラーフロー
5リフレッシュトークンフロー
(Refresh Token Grant Type)
更新トークンフロー

接続アプリケーション

設定項目設定値
OAuthの有効化チェックあり
コールバックURL認可レスポンスのリダイレクト先を指定
選択したOauth範囲認可リクエストを受け付けるスコープ
Webサーバフローの秘密が必要OpentID Connectを使用する場合はチェックあり
IDトークンを設定IDトークンにカスタム属性を含める場合はチェックあり
コンシューマ鍵client_id
として使用
コンシューマの秘密client_secret
として使用

アプリケーションハンドラー

接続アプリケーションにApexで実装したハンドラーを紐づけることで、IDトークンのカスタム属性として値を返却することができます。下記のサンプルは、ログインユーザに紐づく権限セットを返す処理になります。

global class ConnectedAppPluginExample extends Auth.ConnectedAppPlugin{
	global override Map<String,String> customAttributes(Id userId, Id connectedAppId, Map<String,String> formulaDefinedAttributes, Auth.InvocationContext context){ 
		List<PermissionSetAssignment> psas = [SELECT id, PermissionSet.Name FROM PermissionSetAssignment WHERE PermissionSet.IsOwnedByProfile = false AND (AssigneeId = :userId)]; 
		String permsets = '[‘; 
		for (PermissionSetAssignment psa :psas) { 
			permsets += psa.PermissionSet.Name + ';’; 
		} 
		permsets += ']’; 
		formulaDefinedAttributes.put('PermissionSets', permsets); 
		return formulaDefinedAttributes; 
	}
}

参考

OAuth徹底入門 セキュアな認可システムを適用するための原則と実践

一番分かりやすい OAuth の説明
https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be

一番分かりやすい OpenID Connect の説明https://qiita.com/TakahikoKawasaki/items/498ca08bbfcc341691fe

OAuth & OIDC 入門編