スタンドアロンモードでキークロークを実行し、api呼び出しを認証するためにnode.jsアダプターを使用してマイクロサービスを作成しました。
keyclaokからのjwtトークンは、各API呼び出しと共に送信されます。送信されたトークンが有効なものである場合にのみ応答します。
質問1:マイクロサービスからのアクセストークンを検証するにはどうすればよいですか?
ベアラートークンの各リクエストを検査し、APIのルートハンドラーに渡される前にuserinfoエンドポイントでキークロークサーバーによる検証のためにそのトークンを送信する関数を実装します。
キークロークサーバーの特定のエンドポイント(userinfoルートなど)を見つけるには、その 既知の構成 を要求します。
ノードAPIでexpressjsを使用している場合、これは次のようになります。
const express = require("express");
const request = require("request");
const app = express();
/*
* additional express app config
* app.use(bodyParser.json());
* app.use(bodyParser.urlencoded({ extended: false }));
*/
const keycloakHost = 'your keycloak Host';
const keycloakPort = 'your keycloak port';
const realmName = 'your keycloak realm';
// check each request for a valid bearer token
app.use((req, res, next) => {
// assumes bearer token is passed as an authorization header
if (req.headers.authorization) {
// configure the request to your keycloak server
const options = {
method: 'GET',
url: `https://${keycloakHost}:${keycloakPort}/auth/realms/${realmName}/protocol/openid-connect/userinfo`,
headers: {
// add the token you received to the userinfo request, sent to keycloak
Authorization: req.headers.authorization,
},
};
// send a request to the userinfo endpoint on keycloak
request(options, (error, response, body) => {
if (error) throw new Error(error);
// if the request status isn't "OK", the token is invalid
if (response.statusCode !== 200) {
res.status(401).json({
error: `unauthorized`,
});
}
// the token is valid pass request onto your next function
else {
next();
}
});
} else {
// there is no token, don't process request further
res.status(401).json({
error: `unauthorized`,
});
});
// configure your other routes
app.use('/some-route', (req, res) => {
/*
* api route logic
*/
});
// catch 404 and forward to error handler
app.use((req, res, next) => {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
質問2:Keycloakで利用できるトークン検証はありますか?
Keycloakのuserinfoエンドポイントへのリクエストは、トークンが有効であることを確認する簡単な方法です。
有効なトークンからのUserinfo応答:
ステータス:200 OK
{
"sub": "xxx-xxx-xxx-xxx-xxx",
"name": "John Smith",
"preferred_username": "jsmith",
"given_name": "John",
"family_name": "Smith",
"email": "[email protected]"
}
無効な有効なトークンからのUserinfo応答:
ステータス:401未承認
{
"error": "invalid_token",
"error_description": "Token invalid: Token is not active"
}
追加情報:
Keycloakは、 keycloak-connect と呼ばれる独自のnpmパッケージを提供します。ドキュメントでは、ルートでの簡単な認証について説明し、ユーザーがリソースにアクセスするにはログインする必要があります。
app.get( '/complain', keycloak.protect(), complaintHandler );
この方法がベアラのみの認証を使用して機能することはわかりません。私の経験では、この単純な認証方法をルートに実装すると、「アクセス拒否」応答が発生します。 この質問 は、Keycloakアクセストークンを使用してREST APIを認証する方法についても尋ねます。 受け入れられた回答 は、keycloak-connectによって提供される単純な認証方法を使用することを推奨しますが、アレックスはコメントで述べています:
「keyloak.protect()関数はヘッダーからベアラートークンを取得します(取得しません)。ベアラーのみの認証を実行するために、このソリューションをまだ探しています– alex Nov 2 '17 at 14:02
そのために、このUserInfoエンドポイントを使用します。これにより、電子メールなどの他の属性や、マッパーで定義したものを確認することもできます。 Bearer Authorizationを使用してヘッダー属性でアクセストークンを送信する必要があります:Bearer access_token
http:// localhost:8081/auth/realms/demo/protocol/openid-connect/userinfo
トークンを検証する2つの方法があります:
上記のバリアントはオンライン検証です。これはもちろん、検証ごとに別のhttp /往復を導入するため、非常にコストがかかります。
多くのより効率的なオフライン検証:JWTトークンはbase64でエンコードされたJSONオブジェクトであり、がすでに含まれていますオフラインで検証を行うためのすべての情報(クレーム)。公開鍵と署名の検証のみが必要です(内容が「有効」であることを確認するため)。
リモート要求なしでオフラインで検証を実行するいくつかのライブラリ(たとえば keycloak-backend )があります。オフライン検証は次のように簡単です。
token = await keycloak.jwt.verifyOffline(someAccessToken, cert);
console.log(token); //prints the complete contents, with all the user/token/claim information...
公式keycloak-connect
node.jsライブラリ(代わりに keycloak-backend を使用)?公式ライブラリは、ミドルウェアとしてのExpressフレームワークにより重点を置いており、(私が見た限りでは)検証機能を直接公開していません。または、検証は標準化されたプロセスであるため、任意のJWT/OICDライブラリを使用できます。