1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ALB認証

Last updated at Posted at 2024-10-28

ALB認証

メリット

認証処理にてAWS Cognitoを利用する場合、アプリケーションの前にALB(Application Load Balancer)を配置していれば、ALBの認証機能を利用することで、アプリケーション側の実装がシンプルになります。

認証フロー

alb-user-auth-flow.png
image.png

認証フロー図の右上にある「Target」が示すのはアプリケーションです。
ステップ9及び10でアプリケーションが登場します。その時点で認証が既に完了しています。アプリケーションはRequestのHeader項目「X-AMZN-OIDC-*」(x-amzn-oidc-dataやx-amzn-oidc-accesstokenなど)を取得するだけで済みます。

試し

Cognito設定

User pool、App Clientを作成します。
App Client - Hosted UI - Callback URLに、ALBの「oauth2/idpresponse」エンドポイントを設定しておきます。
image.png

ALB Listener設定

ALB Listener設定画面でCognitoの認証情報を設定
・User Pool
・User pool domain
・App client

image.png
image.png

Node.js + express

今回はNode.jsのexpress packageで試しました。

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  console.log(console.log(req));
  res.send('Hello World root!')
})

app.listen(port, () => {
  console.log(`Example app listening on port ${port}`)
})

出力ログ:
image.png

「x-amzn-oidc-*」項目が3つ出力されました。
・x-amzn-oidc-data
・x-amzn-oidc-identity
・x-amzn-oidc-accesstoken

x-amzn-oidc-dataをpythonのpyjwtでdecodeしてみました。

import jwt
x_amzn_oidc_data='eyJ0eXAiOiJKV1。。。。。'
decoded = jwt.decode(t1, options={"verify_signature": False}) 
print("\n".join(list(decoded.keys())))

以下の出力ログから、usernameが含まれていることを確認できました。
・sub
・cognito:groups
・iss
・version
・client_id
・origin_jti
・token_use
・scope
・auth_time
・exp
・iat
・jti
・username

ALBまとめ

ALBを利用することで、アプリケーション側がCognitoの存在を意識する必要がなくなり、request headerから必要なユーザ情報などを取得できます。

Tips

上記のALB認証フロー図におけるステップ4-7は、ALBがCognitoと直接通信します。
Cognitoにはprivate endpointが存在しないため、ALBの利用にはがインターネットアクセスが必須条件です。
Internet Gatewayを使用する環境では基本的には問題ないです。
image.png

しかし、Proxy経由でインターネットにアクセスする場合は、ALB認証を利用できないと考えております。
image.png


ALB認証利用しない場合

ALB認証を利用しない場合、アプリケーションの中にCognitoとやり取りをするロジックを実装する必要です。
Node.js + express + passport + passport-oauth2の例です。

const express = require('express');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const app = express();
const passport = require('passport');
const OAuth2Strategy = require('passport-oauth2').Strategy;

const MemoryStore = require('memorystore')(session);

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(session({
  name : "xxxx",
  resave: 'true',
  saveUninitialized: 'true',
  secret: 'keyboard cat',
  store: new MemoryStore({
    checkPeriod: 24 * 60 * 60 * 1000 // prune expired entries every 24h
  }),
}));
app.use(passport.initialize());
app.use(passport.session());

passport.serializeUser((user, cb) => cb(null, user));
passport.deserializeUser((user, cb) => cb(null, user));

passport.use(new OAuth2Strategy({
  authorizationURL: AUTHORIZATION_URL, // https://xxx.auth.ap-northeast-1.amazoncognito.com/oauth2/authorize
  tokenURL: TOKEN_URL, // https://xx.auth.ap-northeast-1.amazoncognito.com/oauth2/token
  clientID: COGNITO_ClientId, // app client id
  clientSecret: COGNITO_ClientSecret,  // app client secret
  callbackURL: APP_CALLBACK_FULL_URL // callback url
},
  async function (accessToken, refreshToken, params, profile, done) {
    try {
      // decode token
      ...

      done(null, {
        ...
      }) 

    } catch(err) {
      ...
    }
  }
));
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?