Node.js ApplicationsとOracle Identity Cloud Service間の認証について

Node.js WebアプリケーションとOracle Identity Cloud Service間の認証について理解する準備ができています。内容は次のとおりです。

  • Oracle Identity Cloud ServiceがNode.js SDKでサポートする3つのレグ認証フロー

  • Node.jsアプリケーションとともにSDKを使用してOracle Identity Cloud Serviceで認証する場合

  • Node.js SDKのメソッドと関数

3方向認証フローについて

Oracle Identity Cloud Serviceでは、Node.js SDKでの3つのlegged認証フローがサポートされます。このフローでは、ユーザーはOracle Identity Cloud Serviceと直接対話します。ユーザーのサイン・イン後、Oracle Identity Cloud Serviceは、SDKがユーザー・アクセス・トークンと交換する認可コードを発行します。Node.js Webアプリケーションでは、このアクセス・トークンを使用して、ユーザーにアプリケーション内の保護されたリソースへのアクセス権を付与します。3つのレグ化フローでは、認可コード付与タイプを使用します。

セキュリティを強化するために、Oracleは、Node.js WebアプリケーションをOracle Identity Cloud Serviceと統合して認証するために3 leggedフローを使用することをお薦めします。認可コード権限タイプを使用することで、再認証を行わずにOracle Identity Cloud Serviceによって保護されている他のアプリケーションにアクセスすることもできます。

Node.js ApplicationでのSDKの使用について

Node.js Webアプリケーションでは、2つのユースケースが実装されます。1つは認証ユーザー用、もう1つはログイン・ユーザーに関する詳細情報へのアクセス用です。

次のデータ・フロー・ダイアグラムは、各ユースケースのWebブラウザ、WebアプリケーションおよびOracle Identity Cloud Service間のイベント、コールおよびレスポンスのフローを示しています。

ユースケース#1:ユーザーの認証

データ・フローの動作は次のとおりです。

  1. ユーザーが保護されたリソースをリクエストします。

  2. 認証モジュールでは、SDKを使用して、Oracle Identity Cloud Serviceのリクエスト認証コードURLを生成し、このURLをWebブラウザへのリダイレクト・レスポンスとして送信します。

  3. WebブラウザはURLを呼び出します。

  4. Oracle Identity Cloud Service Sign Inページが表示されます。

  5. ユーザーは、Oracle Identity Cloud Serviceサインイン資格証明を送信します。

  6. ユーザーのサイン・イン後、Oracle Identity Cloud Serviceはユーザーのセッションを作成し、認可コードを発行します。

  7. Webアプリケーションは、バックエンド(またはサーバー間)コールを行い、ユーザー・アクセス・トークンの認可コードを交換します。

  8. Oracle Identity Cloud Serviceではアクセス・トークンが発行されます。

  9. セッションが確立され、ユーザーがホーム・ページにリダイレクトされます。

  10. Webアプリケーションのホーム・ページが表示されます。

ユースケース#2:ユーザーに関する詳細の取得

データ・フローの動作は次のとおりです。

  1. ユーザーが/myProfileリソースをリクエストします。

  2. Webアプリケーションは、SDKを使用してOracle Identity Cloud Serviceを呼び出します。SDKは、ユーザー・セッションに格納されているアクセス・トークンをパラメータとして使用します。

  3. ユーザーの詳細がJSONオブジェクトとしてWebアプリケーションに送信されます。

  4. 「プロファイル」ページでは、JSONオブジェクトがHTMLコンテンツとしてレンダリングされます。

メソッドと関数について

Node.js SDKは、Node.js modulesフォルダに追加するNode.jsパスポート戦略です。このSDKは、Node.js約束にも基づいています。Node.js SDKで必要とされるサード・パーティ依存関係はすべて、SDKの package.jsonファイルで定義されます。Node.js Webアプリケーションでは、少なくともこの一連のモジュールを使用する必要があります。

"dependencies": {
    "async": "^2.1.2",
    "bunyan": "^1.8.5",
    "cache-manager": "^2.2.0",
    "json-web-token": "^2.1.3",
    "jsonwebtoken": "^7.1.9",
    "jwk-to-pem": "^1.2.6",
    "jws": "^3.1.4",
    "lru": "^3.1.0",
    "passport": "^0.3.2",
    "promise": "^7.1.1",
    "querystring": "^0.2.0",
    "request": "^2.79.0",
    "rsa-pem-to-jwk": "^1.1.3",
    "util": "^0.10.3"
  },

Node.js Webアプリケーションは、Node.js expressおよびexpress-handlebarsモジュールを使用して開発されました。このモジュールではURLルートが各URLのapp.get()関数の形式で実装されます。

Node.js SDKには、Oracle Identity Cloud Service接続情報にロードされるJSON変数が必要です。Node.js Webアプリケーションでは、ids変数を使用して次の情報を格納します。

var ids = {
    oracle: {
         "ClientId": '123456789abcdefghij',
         "ClientSecret": 'abcde-12345-zyxvu-98765-qwerty',
         "ClientTenant": 'idcs-abcd1234',
         "IDCSHost": 'https://%tenant%.identity.oraclecloud.com',
         "AudienceServiceUrl" : 'https://idcs-abcd1234.identity.oraclecloud.com',
         "TokenIssuer": 'https://identity.oraclecloud.com/',
         "scope": 'urn:opc:idm:t.user.me openid',
         "logoutSufix": '/oauth2/v1/userlogout',
         "redirectURL": 'http://localhost:3000/callback'
    }
};
 
module.exports = ids;

このSDKに必要な各属性の簡単な説明を次に示します。

名前 説明
ClientId Identity Cloud ServiceコンソールにNode.js Webアプリケーションを登録した後に生成されるクライアントIDの値。
ClientSecret Identity Cloud ServiceコンソールにNode.js Webアプリケーションを登録した後に生成されるクライアント・シークレットの値。
ClientTenant Oracle Identity Cloud Serviceインスタンスのドメイン接頭辞。通常、この接頭辞はidcs-abcd1234と似ています。
IDCSHost Oracle Identity Cloud Serviceインスタンスのドメイン接尾辞。実行時に、% tenant % placeholderがClientTenant属性の値に置き換えられます。
AudienceServiceUrl Oracle Identity Cloud Serviceインスタンスの完全修飾ドメイン名URL。
TokenIssuer この属性では、Oracleによって値https://identity.oraclecloud.com/を保持することが推奨されます。
scope

スコープにより、Oracle Identity Cloud Serviceユーザーにかわってアプリケーションがアクセスまたは処理できるデータが制御されます。

アプリケーションでSDKを使用してユーザーを認証する場合、有効範囲はopenidです。アプリケーションでSDKを使用してユーザーの詳細を取得する場合、スコープはurn:opc:idm:t.user.me openidです。

アプリケーションは、logoutSufix属性とredirectURL属性の両方を使用します。SDKでは必要ありません。

Node.jsアプリケーションは、/oauth/oracle URLルートを実装します。ユーザーがOracle Identity Cloud Serviceでの認証を決定すると、WebブラウザはこのURLへのリクエストを行います。このルートでは、SDKを使用して、Oracle Identity Cloud Serviceの認可URLが生成されます。

//Loading the configurations
var auth = require('./auth.js');
 
//Route for /oauth/oracle
app.get("/auth/oracle", function(req, res){
    //Authentication Manager loaded with the configurations.
    am = new IdcsAuthenticationManager(auth.oracle);
    //Using Authentication Manager to generate the Authorization Code URL, passing the
    //application's callback URL as parameter, along with code value and code parameter.
    am.getAuthorizationCodeUrl(auth.oracle.redirectURL, auth.oracle.scope, "1234", "code")
        .then(function(authZurl){
            //Redirecting the browser to the Oracle Identity Cloud Service Authorization URL.
            res.redirect(authZurl);
        }).catch(function(err){
            res.end(err);
        })
});

この関数は、JSONパラメータを変数にロードし、認証マネージャを初期化し、Node.js SDKのIdcsAuthenticationManager.getAuthorizationCodeUrl()関数を使用して認可コードURLを生成します。このファンクションは、約束を使用して、認可コードURLが生成されるときまたはブラウザでエラーをレンダリングするときに、ユーザーのWebブラウザをリダイレクトします。

次のパラメータを使用して、認可コードURLを生成します。

名前 説明
auth.oracle.redirectURL ユーザーがサインインすると、Oracle Identity Cloud ServiceによってユーザーのWebブラウザがこのURLにリダイレクトされます。このURLは、Identity Cloud Serviceコンソールで信頼できるアプリケーション用に構成するURLと一致している必要があります。Node.js WebアプリケーションのリダイレクトURLの指定の詳細は、「Node.js Applicationの登録」を参照してください。
auth.oracle.scope 認証のOAuthまたはOpenID Connectスコープ。このアプリケーションに必要なのはopenid認証のみです。
state OAuthプロトコルは、このパラメータを定義します。Node.js Webアプリケーションの例では、このコードを使用して、Oracle Identity Cloud Serviceに通信を確立できるかどうかをチェックしています。この例では、このパラメータの値は1234です。
response_type 承認コード権限タイプで必要なパラメータ。この例では、このパラメータの値はcodeです。

ユーザーのサインイン後、Oracle Identity Cloud ServiceはユーザーのWebブラウザをコールバックURLにリダイレクトします。このURLは開発者が実装する必要があります。Node.js Webアプリケーションでは、/callbackルートを使用してこのリクエストを処理します。

//Route for /callback
app.get("/callback", function(req,res){
    //Authentication Manager loaded with the configurations.
    var am = new IdcsAuthenticationManager(auth.oracle);
    //Getting the authorization code from the "code" parameter
    var authZcode = req.query.code;
    //Using the Authentication Manager to exchange the Authorization Code to an Access Token.
    am.authorizationCode(authZcode)
        .then(function(result){
            //Getting the Access Token Value.
            res.cookie(config.IDCS_COOKIE_NAME, result.access_token);
            res.redirect('/auth.html');
        }).catch(function(err){
            res.end(err);
        })
});

Node.jsアプリケーションは、承認コードを使用してアクセス・トークンをリクエストします。アクセス・トークンはCookieとして保存され、後で使用するためにWebブラウザに送信されます。

Node.js SDKのIdcsAuthenticationManager.authorizationCode()関数は、プロミス(then - catch文)を使用してアクセス・トークンをCookieとして設定し、ブラウザを/auth.htmlページにリダイレクトします。

Node.js SDKは、Node.js passportフレームワークに基づいています。したがって、/auth URLハンドラにアクセス・トークン変数をヘッダー変数として転送し、Oracle Identity Cloud Service戦略名をパラメータとしてpassport.authenticate()メソッドを使用する必要があります。

//Uses passport to create a User Session in Node.js.
//Passport sets a user attribute in the request as a json object.
app.get('/auth', passport.authenticate(config.IDCS_STRATEGY_NAME, {}), function(req, res) {
   res.redirect('/home');
});

passport.authenticate()メソッドがアプリケーションのセッションを作成すると、この関数によって、ユーザーのWebブラウザが/homeアプリケーションの保護されたURLにリダイレクトされます。/homeに加えて、Node.js Webアプリケーションには、他にも/appDetails/userInfo/myProfileという3つの保護されたURLsがあります。

各保護URLは、ユーザーのセッションが以前に作成されたかどうかを確認する必要があります。これらのURLsのapp.get()関数ごとに、次の関数が使用されます。

function ensureAuthenticated(req, res, next) {
   if (req.isAuthenticated()) {
      return next();
   }
   res.redirect('/login')
}

Node.jsアプリケーションは/myProfileルートを処理し、passport.authenticate()メソッドによってセッション内で設定された情報を次のように取得します。

app.get("/myProfile", ensureAuthenticated, function(req,res){
   //User Manager loaded with the configurations
   var um = new IdcsUserManager(auth.oracle);
   //Using the user id in the request attribute to render the user json in the screen.
   um.getUser(req.user.id)
      .then(function(user){
         res.render('myProfile', {
         layout: 'privateLayout',
         title: 'My Profile',
         user: req.user,
         userInfo: JSON.stringify(user, null, 2)
         });
      }).catch(function(err1){
         res.end(err1);
      })
});

UserManagerオブジェクトの初期化後、/myProfileルートのハンドラはSDKのIdcsUserManager.getUser()関数を使用して、ユーザー・プロファイルを表すJSONオブジェクトを取得します。アプリケーションは、Webブラウザでレンダリングするために、JSONオブジェクトをmyProfile.handlebarsファイルに送信します。

ユーザーをアプリケーション間のシングル・サインオンからOracle Identity Cloud Serviceにサインアウトするには、Node.js Webアプリケーションによって、次のように/logoutルートが実装されます。

app.get('/logout', function(req, res){
   req.logout();
   res.clearCookie();
   res.redirect(auth.oracle.IDCSHost + auth.oracle.logoutSufix);
});

このルートでは、アプリケーションのセッションが無効化され、以前に設定したCookieが削除された後、ユーザーのWebブラウザがOracle Identity Cloud ServiceのOAuthログアウトURLにリダイレクトされます。このURLはJSON構成オブジェクトで設定されます。