Mananda OAuth API Beta
 Mananda Developer Top
マナビ利用ガイド 
Mananda OAuth APIは、アプリケーション(スマホアプリやWebアプリケーションなど)とMananda LRS(Learning Record Store)を接続するOAuth 2.0 ベースのインターフェースを提供します。
1. アカウント作成
Mananda OAuth APIに対応したクライアント・アプリケーション(以下、アプリケーション)の開発には、Manandaアカウントが必要です。まだ、アカウントをお持ちでない場合は、まずManandaログインにある『新規登録』ボタンからアカウントを作成します。登録したメールアドレス宛に本人確認のメールが送信されるので、メール本文に記載されたリンクをたどりログインするとManandaユーザサイトのトップページ(バッジ一覧)が表示されます。
2. Developerサイトへのアクセス
ヘッダ右隅のプロフィールアイコンからMananda Developerサイトとサービスサイトを行き来できるようになっています。サービスサイトから Developer サイトへは一覧の「Developerサイト」、逆に Developer サイトからサービスサイトへは「Manandaサービス」をお選びください。
既にManandaアカウントをお持ちの場合は、直接本Developerサイトにアクセスいただき、AP(Activity Provider)登録時にログインすることもできます。
3. アプリケーションの登録
xAPI(Experience API)では、LRS(Learning Record Store)とステートメントの送受信をするソフトウェアを"Activity Provider(以下、AP)"と呼びます。Mananda LRSとAPは OAuth を介して接続を確立するので、その意味で AP は OAuth クライアントです。OAuthクライアントは一般に、OAuth サーバから発行されたクライアントIDを使用して OAuth サーバに認可を要求します。Mananda OAuth APIでも同様にアプリケーションを事前登録し、クライアントIDを入手する必要があります。
3-1. 各種エンドポイント
Developerサイト上部にある「アプリケーション管理」のリンクを辿るとアプリケーション管理画面に遷移します。この画面ではアプリケーションの登録や登録情報の編集の他、各種エンドポイントの情報を確認できます。
認可要求
OAuthクライアント(AP)がMananda LRSに接続する際、最初にアクセスするエンドポイントです。ここで指定されたエンドポイントに、クエリ文字列として以下の情報を付加した GET リクエストを送信することで、認可コードが発行されます。
  • 事前登録したリダイレクトURIとスコープ
  • 登録時に発行されたクライアントID
  • レスポンスタイプ(=code)
  • クライアントで生成したステート
尚、認可コード要求時にOAuthクライアントの利用者がまだManandaで認証されていない場合、Manandaは利用者に対してログインを要求します。
トークン要求
アクセストークンを要求するエンドポイントです。ここで指定されたURLに、認可要求エンドポイントから受け取った認可コードを含む以下の情報を POST リクエストで送信することでアクセストークンとリフレッシュトークンが発行されます。
  • 認可エンドポイントから受け取った認可コード
  • 事前登録したリダイレクトURI
  • グラントタイプ(=authorization_code)
  • 登録時に発行されたクライアントID
  • 登録時に発行されたクライアントシークレット
  • 認可コード要求時にクライアントで生成したステート

Statement API
xAPIの Statement API を呼び出すエンドポイントです。トークン要求エンドポイントから受け取ったアクセストークンを HTTP リクエストの Authorization ヘッダに Authorization: Bearer [アクセストークン] の形で設定することで、xAPI のStatement API仕様に従ったステートメントの送受信が行えます。
3-2. アプリケーションの登録
はじめてのご利用の場合、アプリケーション管理のアプリケーション一覧には「登録されたアプリケーションがありません」と表示されています。この一覧の下にある「アプリケーションを登録」ボタンを選択すると新しいアプリケーションを登録できます。
エンドポイント情報
※3-1.各種エンドポイント参照
アプリケーション情報
登録するアプリケーションの基本情報です。
ご利用元の法人アプリケーションの公開先をプルダウンから指定します。Manandaを法人でご利用で、且つ開発者権限が付与されている場合はここに法人名もリストされます。
アプリケーション名アプリケーションの名称。必須
アプリケーション説明アプリケーションに関する簡単な説明。必須
リダイレクトURIMananda OAuthサーバが認可レスポンスを返す際のリダイレクト先。必須
ステータス有効、無効から選択。アプリケーションを利用可能とする場合は有効。
利用可能なxAPI EndpointStatement API固定
認証情報
OAuthクライアントの認証情報。認可コード要求、アクセストークン要求の際に使用します。
キークライアントID(client_id)として使用します。
シークレットクライアントシークレット(client_secret)として使用します。
アクセスレベル
OAuthクライアントが要求するリソースとそれに対する操作をスコープとして指定。xAPI仕様では8種類のスコープが定義されていますが、Mananda OAuth APIではその中から以下が指定できます(複数選択可)。
statements/writeステートメントを書き込む。
statements/readアプリケーション利用者に付与された権限の範囲でアクセス可能な全てのステートメントを読み出す。
statements/read/mineアプリケーション利用者が書き込んだステートメントを読み出す。
いわゆる『最少権限の原則』で、必要最低限の権限のみ指定することをお勧めします。
3-3. アプリケーション一覧、編集
登録したアプリケーションは「アプリケーション一覧」にリストされます。一覧には3-2.での登録内容の内、アプリケーション名、キー、シークレット、及び登録日とステータスが表示されます。
また、一覧からアプリケーション名のリンクを辿ることで設定内容を編集できます。
一旦、利用が始まった状態で設定内容を変更する場合は、予めユーザに告知するなど十分に気を付けることをお勧めします。
3-4. アプリケーション削除
一覧された各アプリケーションの左にあるラジオボタンをチェックし、「アプリケーションを削除」ボタンを選択すると、アプリケーションの情報が削除されます。アプリケーションの登録情報を削除しても、それまでに送信されたステートメントはそのままMananda LRSに残ります。
一旦、利用が始まった状態でアプリケーションを削除する場合は、予めユーザに告知するなど十分に気を付けることをお勧めします。
4. 接続フロー
Mananda OAuth APIは RFC 6749 The OAuth 2.0 Authorization Framework で定義されている4種類の認可グラント(Authorization Grant)の中の「認可コード(Authorization Code)」に基づいた認証・認可処理を行います。
xAPI仕様 6.4 Security では"署名付き OAuth 1.0(RFC 5849)", "Basic認証", "Common Access Cards(CAC)"のいづれかをサポートすることを要求していますが、ADL LRS(ADLが公開しているオープンソースLRS)は OAuth 2.0 も想定した実装になっています。
参考資料 Experience API - 6.4 Security
https://github.com/adlnet/xAPI-Spec/blob/master/xAPI.md#security
Using OAuth: adlnet/ADL_LRS WiKi
https://github.com/adlnet/ADL_LRS/wiki/Using-OAuth
4-1. 認可要求
  1. アプリケーションは認可エンドポイントに対して認可要求を送信。
  2. [ユーザが未認証の場合]Manandaはユーザに対してログインを要求。
  3. Manandaはユーザにアプリケーションの情報とアプリケーションがユーザのリソースに対して何を行うか(スコープ)を提示し、同意するか否かを求める
  4. [同意の場合]Manandaは、リクエスト内のリダイレクトURIとアプリケーション登録時に予め設定されたリダイレクトURIが合致していることを確認した上で同URIに、認可コードと(アプリケーションから受け取った)ステートをクエリ文字列として添付し、ブラウザをリダイレクトする
  5. 呼び出されたアプリケーションはクエリ文字列から認可コードとステートを取り出し、アクセストークンのリクエストURLを生成する(4-2. アクセストークン要求参照)
参考資料 The OAuth 2.0 Authorization Framework(RFC 6749)
4.1. Authorization Code Grant
https://tools.ietf.org/html/rfc6749#section-4.1

リクエストメソッドGET
[Endpoint]?client_id=[Client id]
	&redirect_uri=[Redirect URI]
	&response_type=code
	&scope=[Scopes]
	&state=[State]
パラメータタイプ説明
client_idStringアプリケーション登録時に発行されたクライアントID
redirect_uriURIアプリケーション登録時に指定したリダイレクトURI
response_typeString「code」のみ指定可能
scopeStringアプリケーション登録時に指定したスコープ。複数の場合は「,」で区切る
stateStringステートを表す任意の文字列。認可要求を送信するアプリケーション側で生成

リダイレクト
[Redirect URI]?code=[Authorization Code]&state=[State]
パラメータタイプ説明
codeStringManandaがユーザに対して要求されたリソースの認可と認証を行った後に発行する認可コード
stateStringステートを表す任意の文字列。認可要求を送信するアプリケーション側で生成
4-2. アクセストークン要求
  1. リダイレクトで呼び出されたアプリケーションは、クエリ文字列から認可コードを使い、アクセストークンを要求するためのJSONデータを生成し、トークンエンドポイントに送信
  2. Manandaはクライアント認証情報その他、アプリケーションからPOSTされた情報を照会後、アクセストークンとリフレッシュトークンをJSON形式で返す
アクセストークン要求の期限は、認可コード発行から10,000ms(10秒)以内です
参考資料 The OAuth 2.0 Authorization Framework(RFC 6749)>
4.1.3. Access Token Request
https://tools.ietf.org/html/rfc6749#section-4.1.3

リクエストメソッドPOST
	{
	    client_id    : "[Client ID]",
	    client_secret: "[Client Secret]",
	    grant_type   : "authorization_code",
	    code         : "[Authorization Code]",
	    redirect_uri : "[Redirect URI]",
	    state        : "[State]"
	}	
パラメータタイプ説明
client_idStringアプリケーション登録時に発行されたクライアントID
client_secretStringアプリケーション登録時に発行されたクライアントシークレット
grant_typeString「authorization_code」のみ指定可能
codeString認可要求で取得した認可コード
redirect_uriURIアプリケーション登録時に指定したリダイレクトURI
stateStringステートを表す任意の文字列。認可要求を送信するアプリケーション側で生成

レスポンスJSON形式
	{
	    access_token : "[Access Token]",
	    refresh_token: "[Refresh Token]",
	}	
パラメータタイプ説明
access_tokenStringアクセストークン
refresh_tokenStringリフレッシュトークン。アクセストークンのリフレッシュに使用
4-3. アクセストークンのリフレッシュ要求
  1. アプリケーションはリフレッシュトークン、及びクライアントIDその他の情報をトークンエンドポイントにPOSTする
  2. Manandaはリフレッシュトークンとその他アプリケーションから渡された情報を照会後、新しいアクセストークンを生成し、JSON形式でアプリケーションに返す
参考資料 The OAuth 2.0 Authorization Framework(RFC 6749)
6. Refreshing an Access Token
https://tools.ietf.org/html/rfc6749#section-6

リクエストメソッドPOST
	{
	    client_id     : "[Client ID]",
	    client_secret : "[Client Secret]",
	    grant_type    : "refresh_token",
	    code          : "[Authorization Code]",
	    refresh_token : "[Refresh Token]",
	    state         : "[State]"
	}	
パラメータタイプ説明
client_idStringアプリケーション登録時に発行されたクライアントID
client_secretStringアプリケーション登録時に発行されたクライアントシークレット
grant_typeString「authorization_code」のみ指定可能
codeString認可要求で取得した認可コード
refresh_tokenStringアクセストークン要求時に取得したリフレッシュトークン
stateStringステートを表す任意の文字列。認可要求を送信するアプリケーション側で生成
レスポンスJSON形式
	{
	    access_token : "[Access Token]",
	}	
パラメータタイプ説明
access_tokenString新たに発行されたアクセストークン
5. Statement API
xAPIにはStatement API, Document API, State API, Activity Profile API, Agent Profile APIが定義されています。Mananda LRSは現在、この中の Statement API をサポートしています。
5-1. PUT Statements
単一ステートメントの書き込みには PUT リクエストを使用します。

PUTリクエスト時のステートメントIDに関するMananda LRSの仕様

PUTリクエスト時のステートメントにおける制限事項

PUTリクエストの処理フロー

  1. 書き込むステートメントを準備(JSON形式)
  2. xAPI通信のバージョン(※「1.0.1」固定)をHTTPリクエストヘッダに設定
  3. Mananda OAuth API から取得したアクセストークンを HTTPリクエストの Authorizationヘッダに設定
  4. Statement APIエンドポイントに PUT リクエストを送信
  5. Mananda LRS は処理結果に応じてステータスコードを返す
リクエストメッセージヘッダの例PUT
    PUT [Endpoint]?statementId=[Statement ID] HTTP/1.1
    Host: xxxxxxxxx
    Connection: keep-alive
    Content-Length: 942
    Pragma: no-cache
    Cache-Control: no-cache
    Authorization: Bearer [Access Token]
    Origin: http://my.splustar.com
    User-Agent: xxxxxxxxx
    Content-Type: application/json
    X-Experience-API-Version: 1.0.1
    Accept: */*
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: ja,en-US;q=0.8,en;q=0.6
パラメータ説明
AuthorizationBearer [Access Token]アクセストークン
X-Experience-API-Version1.0.1xAPI通信のバージョン(固定)
コード記述例
function sendStatement(statementStr) {
  $.ajaxSetup({
    headers: {
      "X-Experience-API-Version": "1.0.1"
    }
  });
  
  $.ajax({
    type: "PUT",
    url: [Statement API Endpoint]?statementId=[Statement ID],
    contentType: "application/json",
    cache: false,
    data: JSON.stringify(statementStr),
    beforeSend: function(xhr) {
      xhr.setRequestHeader("Authorization", "Bearer " + [Access Token]);
    },
    success: function(d) {
    // 成功時の処理
    },
    error: function(x, s, e) {
    // 失敗時の処理
    },
    complete: function() {
    // 完了処理
    }
  });
}

5-2. POST Statements
※現在、POSTリクエストは未サポートです
5-3. GET Statements
ステートメントの読み出しには GETリクエストを使用します。

GET Statementsに関するMananda LRSのサポート状況

パラメータ使用可否説明
statementId取得するステートメントの ID
voidedStatementId取得する無効ステートメントの ID
agent指定されたAgentやGroupが、ステートメントのアクターやオブジェクトであるステートメントのみをフィルタして返す。
verb特定の verb id とマッチしたステートメントのみを返す。
activity指定された id をもつアクティビティをオブジェクトとするステートメントのみを返す。
registration指定した registration id に一致するステートメントを返す。あるアクティビティに割り当てられるあるアクターに対して、一意の登録 ID が割り当てられることが多いが、それを前提とすべきでないことに注意が必要である。特定のアクターもしくはアクティビティのためのステートメントのみが返されるべき場合には、それらのパラメータもあわせて指定すべきである。
related_activitiesアクティビティ フィルタを広く適用する。Object, 任意のcontextActivities、もしくは、パラメータ本来の振舞の代わりにActivityパラメータに一致するサブステートメントに含まれるそれら任意のプロパティパラメータを持つステートメントを含む。マッチングはActivity パラメータと同様の方式で定義される。
related_agentsエージェント フィルタを広く適用する。Actor, Object, authority, instructor, team。あるいはパラメータ本来の振舞の代わりにAgentパラメータにマッチするサブステートメントに含まれるこれら任意のプロパティを持つステートメントを含む。マッチングはagentパラメータと同様の方式で定義される。
since指定された timestamp よりあと( timestamp の時刻は含まない)に記録されたステートメントのみを返す。
until指定された timestamp と同時またはそれ以前に記録されたステートメントのみを返す。
limit返すステートメントの最大数。0 はサーバが許容する最大値を返すことを表す。
format ids
Agent, Activity、そしてグループオブジェクトを識別するために最低限必要な情報のみを含む。匿名グループにおいては各メンバを識別するために必要な最低限の情報を意味する。

exact
受信したステートメントと完全に同一なAgent, Activity、そしてグループオブジェクトを返す。

canonical
言語フィルタを適用し、オリジナルのAgentオブジェクトを「exact」モードで返したのち、 LRS により判断され、正規の定義を含んだActivityオブジェクトを返す。アクティビティ オブジェクトは名前と説明のために Language Map オブジェクトを含む。これらのマップではひとつの言語のみが返されるべきである。

LRS は、RFC 2616 (HTTP 1.1)で解説されている通り、Accept-Language ヘッダを適用する。ただし、全体としてリソース(ステートメントのリスト)に適用される場合ではなく、このロジックが各言語マップに個別に適用される場合はこの限りではない。LRS がこれらをインポートすることを目的としてステートメントを要求する場合には、「exact 」フォーマットを用いるべきである。
attachmentstrueの場合、LRS はマルチパートレスポンスフォーマットを用いなければならず、あらゆる添付文書を含めなければならない。それ以外の場合には LRS は添付文書の生データを含めてはならず、Content-Type application/json の形式で所定の応答を送信しなければならない。
ascendingtrue の場合、格納された時間の昇順で結果を返す。
各パラメータの詳細はExperience API - 7.2.3 GET Statementsをご確認ください。

GETリクエストの処理フロー

  1. xAPI通信のバージョン(1.0.1)をHTTPリクエストヘッダに設定
  2. Mananda OAuth API から取得したアクセストークンを HTTPリクエストの Authorizationヘッダに設定
  3. 必要に応じてクエリパラメータを生成する
  4. Statement APIエンドポイントにリクエストを送信する
リクエストメッセージヘッダの例GET
    GET [Endpoint]?registration=[Target value] HTTP/1.1
    Host: xxxxxxx
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    Authorization: Bearer [Access Token]
    Origin: xxxxxxxx
    User-Agent: xxxxxxxxx
    Content-Type: application/json
    X-Experience-API-Version: 1.0.1
    Accept: */*
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: ja,en-US;q=0.8,en;q=0.6
パラメータ説明
AuthorizationBearer [Access Token]アクセストークン
X-Experience-API-Version1.0.1xAPI通信のバージョン(固定)
コード記述例 - リクエストの送信
function getStatement(endpoint, queryStr) {
  $.ajaxSetup({
    headers: {
      "X-Experience-API-Version": "1.0.1"
    }
  });
  
  $.ajax({
    type: "GET",
    url: endpoint + "?" + queryStr,
    contentType: "application/json",
    cache: false,
    beforeSend: function(xhr) {
      xhr.setRequestHeader("Authorization", "Bearer " + [Access Token]);
    },
    success: function(d) {
    // 成功時の処理
    },
    error: function(x, s, e) {
    // 失敗時の処理
    },
    complete: function() {
    // 完了処理
    }
  });
}
コード記述例 - クエリパラメータの生成
// クエリパラメータ activity の生成
var activityId = "https://www.digital-knowledge.co.jp/xapi/activities/course/001";
var paramActivity = "activity=" + encodeURI(activityId);

// クエリパラメータ agent の生成
var mbox = {"mbox": "mailto:demouser@demo.jp"},
    encMbox = encodeURI(JSON.stringify(mbox));
var paramAgent = "agent=" + encMbox;
5-4. TinCanJS
TinCanJSは、米国Rustici Software社が公開しているJavascriptライブラリです。アプリケーションはMananda LRSとのステートメント送受信を、このTinCanJSで実装することも可能です。
TinCanJS及びAPIドキュメントは以下のサイトから入手できます
TinCanJS by RusticiSoftware

通信設定
var tincan = new TinCan();
var lrs = new TinCan.LRS({
	endpoint: [Statement API Endpoint],
	version: "1.0.1",
	auth: 'Bearer ' + [Access Token],
	allowFail: false
});
tincan.addRecordStore(lrs);
ステートメントの組み立て
// Actor
var actor = new TinCan.Agent({
		name: "demouser",
		mbox: "mailto:demouser@demo.jp"
});

// Verb
var verb = new TinCan.Verb();
verb.id = "http://adlnet.gov/expapi/verbs/experienced";
verb.display = {
	"ja-JP": "経験した",
	"en-US": "experienced"
}

// Activity ※ Object として処理される
var activityDefinition = new TinCan.ActivityDefinition();

activityDefinition.type = "http://activitystrea.ms/schema/1.0/application";
activityDefinition.name = {
		"ja-JP": "xAPIサンプルアクティビティ",
		"en-US": "xAPI Sample Activity"
};

var activity = new TinCan.Activity();
activity.id = "https://www.digital-knowledge.co.jp/xapi/activities/sample";
activity.definition = activityDefinition;

// Result & Score
var result = new TinCan.Result(),
		score = new TinCan.Score();
		
result.duration = TinCan.Utils.convertMillisecondsToISO8601Duration("3000000");
result.response = "よく頑張りました";

score.max = 100;
score.min = 0;
score.raw = 78.9;
result.score = score;

// Statement
var statement = new TinCan.Statement({
	actor: actor,
	verb: verb,
	target: activity,
	result
});
LRSへのステートメント送信
tincan.sendStatement(statement);
5-5. cURL による確認
コマンドラインツール cURL でMananda LRS からステートメントを GET 要求する場合、-Hオプションでアクセストークンを指定した上で Statement API 仕様に従い、検索パラメータを指定します。以下にregistrationで検索する例を示します。
C:$ curl -H "Authorization:Bearer [Access Token]" 
	-i https://api.mananda.jp/lrs_1/xAPI/statements?registration=[Registration ID]
HTTP/1.1 200 OK
Access-Control-Allow-Methods: POST, PUT, GET, DELETE, OPTIONS
	:
Content-Length: 1016
Connection: keep-alive

{"statements":[{"verb":{"display":{"en-US":"borrowed",
	:
,"timestamp":"2015-11-26T07:51:16.804Z"}]}
6. Manandaサービス上での確認
アプリケーションユーザはステートメントが送信されたことをManandaサービスの「タイムライン」画面で確認できます。
また、アプリケーションが送信するステートメントのアクティビティIDを「e-Learningマナビ」と呼ばれるManandaサービス内のAP(Activity Provider)に登録すれば、特定のアクティビティが完了したタイミングで、修了証となるバッジをユーザに自動発行することもできるようになります。詳しくは『マナビ利用ガイド』をご覧ください。

Mananda Developer目次
xAPI(Experience API)とは
xAPI(Experience API)の概要です。
Mananda OAuth API Beta
このページです。
マナビ利用ガイド
Mananda OAuth API対応アプリケーションとManandaのマナビ、バッジを連携させる方法を解説しています。