Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

【BTP】Node.jsとPostgreSQLでシンプルなアプリケーションを作成(3)Approuter編

$
0
0
はじめに この記事は、Node.jsとPostgreSQLでシンプルなアプリケーションを作成するシリーズの3回目です。 この記事のゴール Approuterを使用して認証を行う Approuterを介さないサービスへのアクセスをブロックする CRUD処理に必要な権限をチェックする ステップ Approuterを使用して認証を行う Approuterを介さないサービスへのアクセスをブロックする CRUD処理に必要な権限をチェックする 1. Approuterを使用して認証を行う 1.1. Approuterモジュールを追加 プロジェクト直下にapprouterというフォルダを追加します。 node-postgres-sample  └ approuter  └ srv  └ mta.yaml 1.2. approuter/package.jsonの設定 approuterフォルダにpackage.jsonを追加します。 approuter/package.json { "name": "approuter", "version": "1.0.0", "scripts": { "start": "node node_modules/@sap/approuter/approuter.js" }, "dependencies": { "@sap/approuter": "^10.4.0" } } 1.3. approuter/xs-app.jsonの設定 approuterフォルダにxs-app.jsonファイルを追加します。このファイルによって入ってきたリクエストをNode.jsアプリのURLにルーティングします。 approuter/xs-app.json { "welcomeFile": "index.html", "authenticationMethod": "route", "routes": [ { "source": "^/node-pg/", "target": "/", "authenticationType": "xsuaa", "destination": "srv-api" } ] } welcolmeFile(index.html)は、approuter/resourcesの中に作成します。これはApprouterのURLを叩いたときに最初に表示されるページです。 approuter/resources/index.html <body> Welcome to App Router default web page <br> </body> 1.4 mta.yamlの調整 mta.yamlにApprouterモジュールを追加します。 mta.yaml modules: - name: node-postgres-sample-approuter type: approuter.nodejs path: approuter parameters: disk-quota: 512M memory: 512M requires: - name: node-postgres-sample-uaa - name: srv-api group: destinations properties: name: srv-api url: "~{srv-url}" forwardAuthToken: true resourcesセクションにXSUAAサービスを追加します。 - name: node-postgres-sample-uaa type: org.cloudfoundry.managed-service parameters: path: ./xs-security.json service-plan: application service: xsuaa プロジェクト直下にxs-security.jsonを作成します。これはXSUAAの設定用のファイルです。 xs-security.json { "xsappname": "node-postgres-sample", "tenant-mode": "dedicated", "scopes": [ { "name": "uaa.user", "description": "UAA" } ], "role-templates": [ { "name": "Token_Exchange", "description": "UAA", "scope-references": [ "uaa.user" ] } ] } 1.5 ビルド、デプロイ ビルド、デプロイした後、シークレットモードでApprouterのURLにアクセスします。 ログインを求められるので、XSUAAを使用した認証が有効になっていることが確認できます。 ログインすると、Welcomeページが表示されます。 URLの末尾を/node-pg/productsとすると、productsのデータにアクセスできます。これでNode.jsのアプリケーションにリクエストが転送されていることが確認できました。 もともとのサービスのURLをシークレットモードで開いてみます。 こちらは認証なしでアクセスできます。現状、直接サービスのURLを叩いた場合は認証されていないユーザでもアクセスできる状態です。 2. Approuterを介さないサービスへのアクセスをブロックする 2.1. Dependencyを追加 srvフォルダに移動し、以下のDependencyを追加します。 npm i @sap/xssec passport @sap/xssec: HTTPヘッダに渡されたアクセストークンを検証したり、認証情報にアクセスするためのモジュール passport: 認証を行うためのミドルウェア。任意のStrategyを利用して認証を行うことができる package.jsonのdependenciesセクションは以下のようになります。 srv/package.json "dependencies": { "@sap/xsenv": "^3.1.0", "@sap/xssec": "^3.2.1", "body-parser": "^1.19.0", "express": "^4.17.1", "passport": "^0.4.1", "pg-promise": "^10.10.2" } 2.2. passportを使用したトークンチェックの追加 server.jsに以下のコードを追加します。 srv/server.js 'use strict'; const express = require('express') const bodyParser = require('body-parser') //追加-------------------------------------------------- const passport = require('passport') const JWTStrategy = require('@sap/xssec').JWTStrategy const xsenv = require('@sap/xsenv') //------------------------------------------------------ const dbConn = require('./db-conn') const dbOp = require('./db-op') var _db = undefined const app = express() app.use(bodyParser.json()) //追加-------------------------------------------------- passport.use(new JWTStrategy(xsenv.getServices({xsuaa:{tag:'xsuaa'}}).xsuaa)); app.use(passport.initialize()); app.use(passport.authenticate('JWT', { session: false })); //------------------------------------------------------ リクエストヘッダにJWTトークンが存在し、認証が成功すると以下のオブジェクトにアクセス可能になります。これらのオブジェクトを追加の権限チェック(たとえば、ユーザが指定したスコープを持っているか)に使うことができます。(@sap/xssecの"Usage with Passport Strategy"セクションを参照) オブジェクト 説明 request.user ユーザのID(id)、名前(name)、メールアドレス(emails)などの情報 request.authInfo Security Contextのオブジェクト。利用可能なメソッドについてはリンク先の"API Description"のセクションを参照。 request.tokenInfo TokenInfoオブジェクト(※)。トークンの情報にアクセスできる。 ※ドキュメントのTokenInfoオブジェクトに関するリンクが切れていたので、持っているメソッドについて確認した。結果は以下の通り。 reset isDecoded isValid getErrorObject getTokenValue getHeader getPayload getExpirationDate getIssuedAt getIssuer getSubject getAudiencesArray getUserId getZoneId getClientId isTokenIssuedByXSUAA verify 2.3 mta.yamlの調整 node-postgres-sample-srvのrequresセクションにnode-postgres-sample-uaaを追加します。 mta.yaml - name: node-postgres-sample-srv type: nodejs path: srv provides: - name: srv-api properties: srv-url: ${default-url} build-parameters: ignore: ["node_modules/"] requires: - name: cap-posgre-sample-db - name: node-postgres-sample-uaa 2.3 ビルド、デプロイ ビルド、デプロイした後、シークレットモードでサービスのURLにアクセスします。 Unauthorizedとなりました。サービスのURLを直接叩いた場合はアクセスできなくなっています。 Approuterを経由した場合はアクセス可能です。 3. CRUD処理に必要な権限をチェックする サービスで実行可能な操作は以下の通りです。各操作に対し、必要な権限(スコープ)を設定します。 URI HTTPメソッド 操作 必要な権限(スコープ) /  GET  "Hello!"を表示  -  /products  GET  すべてのproductを表示  DisplayまたはUpdate  /products/:id  GET  指定したidのproductを表示  DisplayまたはUpdate  /products  POST  productを登録  Update  /products  PUT  productを変更  Update  /products  DELETE  productを削除  Update  3.2. xs-security.jsonを更新 xs-security.jsonでDisplay、およびUpdate用のスコープとそれらのスコープを持つロールテンプレートを定義します。 xs-security.json { "xsappname": "node-postgres-sample", "tenant-mode": "dedicated", "scopes": [ { "name": "$XSAPPNAME.Display", "description": "Display Products" }, { "name": "$XSAPPNAME.Update", "description": "Update Products" } ], "role-templates": [ { "name": "Viewer", "description": "View Products", "scope-references": [ "$XSAPPNAME.Display" ] }, { "name": "Manager", "description": "Maintain Products", "scope-references": [ "$XSAPPNAME.Display", "$XSAPPNAME.Update" ] } ] } 3.3. approuter/xs-app.jsonを更新 特定の操作(URIとHTTPメソッドの組み合わせ)に対して、ユーザが所定のスコープを持っているかどうかをApprouterでチェックします。 approuter/xs-app.json { "welcomeFile": "index.html", "authenticationMethod": "route", "routes": [ { "source": "^/node-pg/products(.*)$", "target": "/products$1", "authenticationType": "xsuaa", "destination": "srv-api", "scope": { "GET": ["$XSAPPNAME.Display", "$XSAPPNAME.Update"], "default": "$XSAPPNAME.Update" } }, { "source": "^/node-pg/", "target": "/", "authenticationType": "xsuaa", "destination": "srv-api" } ] } productsで始まるURIとそれ以外で権限チェックの有無が変わるので、ルートを分けています。 productsで始まるURIの場合(1つ目のルート) GETリクエストに対して、ユーザが$XSAPPNAME.Displayまたは$XSAPPNAME.Updateのスコープを持っているかチェックする・・・scope.GET それ以外のHTTPメソッドに対しては$XSAPPNAME.Updateのスコープを持っているかをチェックする・・・scope.default products始まりでないURIの場合(2つ目のルート) スコープのチェックは行わない 3.3 ビルド、デプロイ ビルド、デプロイした後、シークレットモードでApprouterのURLにアクセスします。 /node-pg/productsにアクセスすると、Forbiddenとなります。 /node-pg/products/1も同様です。 /node-pg/にはアクセスできます。 3.4 ユーザにロールを割り当て デプロイの結果、Approuterのアプリケーションに対して2つのロールテンプレートが作成されています。まずは、Viewerロールを自分のユーザに割り当てます。 Security>Role Collectionsのメニューからロールコレクションを追加します。 ロールコレクションにViewerロールと、自分のユーザを割り当てます。 ロールを割り当てた後、シークレットウインドウからログインしなおし、/node-pg/productsにアクセスしてみます。 /node-pg/products/1にもアクセスできます。 POST、PUT、DELETEについてはブラウザからテストができないため、UIを作成してから確認することにします。 まとめ この記事では、以下を実施しました。 Approuterを使用して認証を行う Approuterを介さないサービスへのアクセスをブロックする CRUD処理に必要な権限をチェックする 次回はサービスを使用したUIを作成したいと思います。

Viewing all articles
Browse latest Browse all 8691

Trending Articles