「開発:OAuth 2 API」の版間の差分

提供:MoodleDocs
移動先:案内検索
編集の要約なし
編集の要約なし
22行目: 22行目:


=== ユーザフィールドマッピング User field mappings ===
=== ユーザフィールドマッピング User field mappings ===
OAuth 2サービスに関して私たちが知るべき他の情報はユーザ情報をMoodleのユーザフィールドにマッピングする方法です。The other information we need to know about an OAuth 2 service is how to map the user information into Moodle user fields. We do this by adding to the list of user field mappings for the Issuer. The mappings for Open ID Connect services are standard and will be automatically created when setting up an Open ID compliant service - for other services you will need to create the mappings manually. Moodle will use this information to import the user profile fields when creating new accounts. The most important user field mappings are the username and email which are used to identify the Moodle account associated with the OAuth 2 login.
OAuth 2サービスに関して私たちが知るべき他の情報はユーザ情報をMoodleのユーザフィールドにマッピングする方法です。We do this by adding to the list of user field mappings for the Issuer. The mappings for Open ID Connect services are standard and will be automatically created when setting up an Open ID compliant service - for other services you will need to create the mappings manually. これは発行者用のユーザフィールドマッピングのリストにユーザ情報を追加することによりマッピングします。Open ID Connectサービス用のマッピングは標準的なもので Open ID に準拠したサービスをセットアップする際に自動的に作成されます。Moodle will use this information to import the user profile fields when creating new accounts. The most important user field mappings are the username and email which are used to identify the Moodle account associated with the OAuth 2 login.





2023年2月2日 (木) 15:06時点における版

OAuth 2 API

Moodle 3.3


作成中です - Mitsuhiro Yoshida (トーク)

OAuth 2 APIはリモートシステムとの統合のためのOAuth 2機能を提供するクラス群です。これらは「/lib/classes/oauth2/」フォルダに存在します。また注意すべきいくつかのコンセプトがあります。

イシュア

OAuthイシュアとはOAuthアクセストークンを発行してIDおよびAPIアクセスを提供する名前付きの外部システムです。これらは「サイト管理 -> サーバ -> OAuth 2サービス」で手動設定できます。一般的なOAuthアクセストークンはテンプレート (Google、Office 365、Facebook) からすぐに作成できます。イシュアは名前およびアイコン(ログインページに表示)、クライアントIDおよびクライアントシークレット (OAuth仕様の一部) を持ちます。

エンドポイント

OAuth発行者はアクセストークンの取得および交換、ID情報の取得に使用するURLであるいくつかのエンドポイントを定義しておく必要があります。テンプレートから作成したOAuthサービスおよびOpen ID Connectを使ったOAuthサービスではこれらは自動的に設定されます。

定義すべき標準的なエンドポイントは「認証エンドポイント」「トークンエンドポイント」「ユーザ情報エンドポイント」の3つです。これはOAuthプロトコルによって「ユーザのログインを許可」「APIにアクセスするためのトークンを取得」「ログインしたユーザ情報を取得」するための3つのURLとなります。

Open ID Connect

Open ID ConnectはOAuth 2の上に構築されたプロトコルであり、OAuth 2ベースのサービスに標準化および相互運用性を提供します。もし「基本サービスURL」が発行者に入力された場合、Moodleはこのサービスの設定を完了するために必要な他のエンドポイントに関するすべての情報を提供する「よく知られた設定」を取得するよう試みます。例) Googleの場合 - 基本サービスのURLは「https://accounts.google.com/」です。このURLに「.well-known/openid-configuration」 を付加してhttps://accounts.google.com/.well-known/openid-configurationにあるサービス説明文を閲覧できます。説明文にはこのサービスの設定を自動的に完了させるために必要な情報すべてを含みます。これはOpen ID connectに準拠したサービスであればどれでも動作します。

Open Badge Connect API

Open Badge Connect APIはIMS Global社により策定されたOAuth 2ベースサービスの標準化および相互運用性を提供するための仕様です。イシュアに「基本サービスURL」が入力された場合、Moodleはこのサービスの設定を完了するために必要なエンドポイントに関するすべての情報を提供する「よく知られた設定」(well-known/badgeconnect.json) を取得するよう試みます。さらにクライアントIDおよびシークレットが与えられていない場合、それらを取得するために登録エンドポイントがコールされます (そして管理者に安全な時間および労力を提供します)。 例) IMS Globalテストプラットフォームの場合、基本サービスのURLは「https://dc.imsglobal.org/」です。私たちはこのURLに「.well-known/badgeconnect.json」を追加してこのサービスのセットアップを自動的に完了するために必要なすべての情報 (エンドポイント、クライアントIDと秘密、画像...) を含むサービスの説明を確認できます。

ユーザフィールドマッピング User field mappings

OAuth 2サービスに関して私たちが知るべき他の情報はユーザ情報をMoodleのユーザフィールドにマッピングする方法です。We do this by adding to the list of user field mappings for the Issuer. The mappings for Open ID Connect services are standard and will be automatically created when setting up an Open ID compliant service - for other services you will need to create the mappings manually. これは発行者用のユーザフィールドマッピングのリストにユーザ情報を追加することによりマッピングします。Open ID Connectサービス用のマッピングは標準的なもので Open ID に準拠したサービスをセットアップする際に自動的に作成されます。Moodle will use this information to import the user profile fields when creating new accounts. The most important user field mappings are the username and email which are used to identify the Moodle account associated with the OAuth 2 login.


How a new issuer service should be implemented?

Any OAuth2 Service should have a class into the lib/classes/oauth2/service/ folder extending from a discovery system (core\oauth2\discovery\base_definition) and implementing core\oauth2\service\issuer_interface:

  • Discovery system indicates the way the endpoints should be obtained.
  • Issuer interface has several common methods, called from lib/classes/oauth2/api.php to initialise or discover endpoints.
class google extends openidconnect implements issuer_interface {
[...]

class imsobv2p1 extends imsbadgeconnect implements issuer_interface {
[...]


I set up an OAuth 2 Issuer - how do I use it in code?

Any plugin that wants to use the configuration information provided by an OAuth issuer first needs to determine which issuer they should use for authentication. This is typically done by adding a setting that lets the admin choose from the list of configured issuers. An example is the "Google Drive" repository. It's possible to have multiple, very similar OAuth Issuers configured e.g. One public Google Issuer and one that is restricted to a specific domain. Once we know the Issuer we wish to use we can use it's ID to get an \core\oauth2\client class which will let us make requests against that API.

// Get an issuer from the id.
$issuer = \core\oauth2\api::get_issuer($issuerid);
// Get an OAuth client from the issuer.
$client = \core\oauth2\api::get_user_oauth_client($this->issuer, $returnurl, $scopes);

Despite what is said in the code documentation, it is best to check that the client is authenticated and if not, redirect the user to log in.

if (!$client->is_logged_in()) {
    redirect($client->get_login_url());
}

What is return URL?

This is a url that will take you back to the current page. The way OAuth works is that the call to get the OAuth client will check to see if we have a valid session with all of the required scopes. If we don't - the user will be redirected immediately to the OAuth login page. When they have logged in - they are redirected back to the "returnurl" in Moodle which must end up making the same call to get an OAuth client - except this time we have a valid session so the client is returned. The returnurl MUST include the sesskey as one of the parameters.

What are the scopes?

These are named "permission grants" which the user is asked to accept. E.g. "email" is a scope which allows Moodle to see the email address for your logged in account. Each of the requested permissions will be displayed to the user with a description of what they mean and the user will have to "grant" Moodle this level of access - or cancel the operation. It is best practice not to request more scopes than are needed at any one time, and to incrementally request additional scopes as they are going to be used by different features in Moodle. For example - when logging into Moodle we only need to request access to the users basic profile and email address. When accessing a repository - we will need to request read/write access to the users files. Each time we create an oauth client class, we list the scopes that we will be using with this instance of the oauth client - if the user has only approved some of the scopes we request - they will be redirected to a consent screen where they approve the additional level of access.

So - what can I do with my oauth client ?

Make requests! This class extends the moodle curl class but includes authentication information with each request automatically. This means you can use standard functions like $client->get() or $client->post() to manually call rest api functions. This class will also honour the configured Moodle security settings like ipaddress black lists and proxy settings.

How do I make it easier to call API functions?

There is an abstract class \core\oauth2\rest which contains helper functions to allow you to wrap a external rest api in an easier to use class. To use it, make a subclass in your own plugin and define the "get_api_functions()" method.

/**                                                                                                                                 
 * Google Drive Rest API.                                                                                                           
 *                                                                                                                                  
 * @package    fileconverter_googledrive                                                                                            
 * @copyright  2017 Damyon Wiese                                                                                                    
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later                                                             
 */                                                                                                                                 
namespace fileconverter_googledrive;                                                                                                
                                                                                                                                    
defined('MOODLE_INTERNAL') || die();                                                                                                
                                                                                                                                    
/**                                                                                                                                 
 * Google Drive Rest API.                                                                                                           
 *                                                                                                                                  
 * @copyright  2017 Damyon Wiese                                                                                                    
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later                                                             
 */                                                                                                                                 
class rest extends \core\oauth2\rest {                                                                                              
                                                                                                                                    
    /**                                                                                                                             
     * Define the functions of the rest API.                                                                                        
     *                                                                                                                              
     * @return array Example:                                                                                                       
     *  [ 'listFiles' => [ 'method' => 'get', 'endpoint' => 'http://...', 'args' => [ 'folder' => PARAM_STRING ] ] ]                
     */                                                                                                                             
    public function get_api_functions() {                                                                                           
        return [                                                                                                                    
            'create' => [                                                                                                           
                'endpoint' => 'https://www.googleapis.com/drive/v3/files',                                                          
                'method' => 'post',                                                                                                 
                'args' => [                                                                                                         
                    'fields' => PARAM_RAW                                                                                           
                ],                                                                                                                  
                'response' => 'json'                                                                                                
            ],                                                                                                                      
            'delete' => [                                                                                                           
                'endpoint' => 'https://www.googleapis.com/drive/v3/files/{fileid}',                                                 
                'method' => 'delete',                                                                                               
                'args' => [                                                                                                         
                    'fileid' => PARAM_RAW                                                                                           
                ],                                                                                                                  
                'response' => 'json'                                                                                                
            ],                                                                                                                      
        ];                                                                                                                          
    }                                                                                                                               
}

This example defines 2 functions in the external API 'create' and 'delete'. It specifies the http methods to use when calling these functions as well as the list of parameters. It also specifies that these functions return 'json' which means that the rest class will automatically decode the json response into an object. The url for each function call can contain parameters in the url (marked with curly braces). These will be replaced when they are passed as arguments to the function. Any remaining arguments will be appended as query parameters.

To use this class - we pass the oauth2 client to the constructor and then use the "call" method to call functions from the api.

$service = new \fileconverter_googledrive\rest($client);           

$params = ['fileid' => $fileid];                                                                                                                          

$service->call('delete', $params);

How do I call API functions when the user is not logged in (e.g. from a scheduled task)?

Moodle allows you to connect a "system account" to any of the OAuth issuers. This is optional - so before enabling functionality that relies on this level of access you should check that the system account has been connected:

if ($issuer->is_system_account_connected()) {
    // Rock and roll.
}

If a system account has been connected - we can use it to get an authenticated oauth client (no redirects involved).

$client = \core\oauth2\api::get_system_oauth_client($issuer);

This client can now be used to access apis as the Moodle system user.

If your code is going to use additional login scopes with this API - it must list all of the scopes it will use in a callback function so that the Moodle administrator can consent and agree to all the scopes when they connect the system account.

**                                                                                                                                 
 * Callback to get the required scopes for system account.                                                                          
 *                                                                                                                                  
 * @param \core\oauth2\issuer $issuer                                                                                               
 * @return string                                                                                                                   
 */                                                                                                                                 
function fileconverter_googledrive_oauth2_system_scopes(\core\oauth2\issuer $issuer) {                                              
    if ($issuer->get('id') == get_config('fileconverter_googledrive', 'issuerid')) {                                                
        return 'https://www.googleapis.com/auth/drive';                                                                             
    }                                                                                                                               
    return '';                                                                                                                      
}

The way the system account works is that a Moodle admin "connects" the system account by logging in with this account and accepting the permissions from the "Site administration -> Server -> OAuth 2 Services" page. One of the permissions they must accept is for offline access. This means that Moodle will receive a refresh token and can store it against that issuer. When we need to get a logged in OAuth client - we can exchange the refresh token for an access token directly, without having to login. The refresh token is updated by a scheduled task to make sure it never expires.