| 1 | KEYCLOAK_BASE_URL=http://192.168.42.102:8080 |
| 2 | KEYCLOAK_REALM=MyRealm |
| 3 | KEYCLOAK_CLIENT_ID=my-app |
| 4 | KEYCLOAK_CLIENT_SECRET=DgL6JibOXWzMWvQ2hZOLoeOcg0IfSVsU |
| 5 | FLASK_SECRET_KEY=your_flask_secret_key |
app.py
· 1.8 KiB · Python
Eredeti
from flask import Flask, redirect, url_for, session, request
from authlib.integrations.flask_client import OAuth
import os
from dotenv import load_dotenv
load_dotenv()
app = Flask(__name__)
app.secret_key = os.getenv("FLASK_SECRET_KEY") # 從環境變數讀取
oauth = OAuth(app)
# 建立 Keycloak 的 OIDC 設定
# 透過 server_metadata_url 來自動取得 OIDC Discovery 設定
keycloak = oauth.register(
name='keycloak',
client_id=os.getenv("KEYCLOAK_CLIENT_ID"),
client_secret=os.getenv("KEYCLOAK_CLIENT_SECRET"),
server_metadata_url=f"{os.getenv('KEYCLOAK_BASE_URL')}/realms/{os.getenv('KEYCLOAK_REALM')}/.well-known/openid-configuration",
client_kwargs={
'scope': 'openid profile email', # 根據需求調整
}
)
@app.route('/')
def homepage():
return '歡迎!<a href="/login">使用 Keycloak 登入</a>'
@app.route('/login')
def login():
# 生成一個隨機 nonce,作為一次性驗證令牌
nonce = os.urandom(16).hex()
session['nonce'] = nonce
return keycloak.authorize_redirect(
redirect_uri=url_for('auth', _external=True),
nonce=nonce
)
@app.route('/auth')
def auth():
# 取得 Keycloak 回傳的參數並換取 token
token = keycloak.authorize_access_token()
nonce = session.get('nonce')
user_info = keycloak.parse_id_token(token, nonce=nonce)
# 將使用者資訊存入 session,並清除 nonce,避免重複驗證
session['user'] = user_info
session.pop('nonce', None)
# 重導到乾淨的頁面
return redirect(url_for('profile'))
@app.route('/profile')
def profile():
user_info = session.get('user')
if user_info:
return f"歡迎, {user_info.get('name', '使用者')}!"
return redirect(url_for('homepage'))
if __name__ == '__main__':
app.run(debug=True)
| 1 | from flask import Flask, redirect, url_for, session, request |
| 2 | from authlib.integrations.flask_client import OAuth |
| 3 | import os |
| 4 | from dotenv import load_dotenv |
| 5 | |
| 6 | load_dotenv() |
| 7 | |
| 8 | app = Flask(__name__) |
| 9 | app.secret_key = os.getenv("FLASK_SECRET_KEY") # 從環境變數讀取 |
| 10 | |
| 11 | oauth = OAuth(app) |
| 12 | |
| 13 | # 建立 Keycloak 的 OIDC 設定 |
| 14 | # 透過 server_metadata_url 來自動取得 OIDC Discovery 設定 |
| 15 | keycloak = oauth.register( |
| 16 | name='keycloak', |
| 17 | client_id=os.getenv("KEYCLOAK_CLIENT_ID"), |
| 18 | client_secret=os.getenv("KEYCLOAK_CLIENT_SECRET"), |
| 19 | server_metadata_url=f"{os.getenv('KEYCLOAK_BASE_URL')}/realms/{os.getenv('KEYCLOAK_REALM')}/.well-known/openid-configuration", |
| 20 | client_kwargs={ |
| 21 | 'scope': 'openid profile email', # 根據需求調整 |
| 22 | } |
| 23 | ) |
| 24 | |
| 25 | @app.route('/') |
| 26 | def homepage(): |
| 27 | return '歡迎!<a href="/login">使用 Keycloak 登入</a>' |
| 28 | |
| 29 | @app.route('/login') |
| 30 | def login(): |
| 31 | # 生成一個隨機 nonce,作為一次性驗證令牌 |
| 32 | nonce = os.urandom(16).hex() |
| 33 | session['nonce'] = nonce |
| 34 | return keycloak.authorize_redirect( |
| 35 | redirect_uri=url_for('auth', _external=True), |
| 36 | nonce=nonce |
| 37 | ) |
| 38 | |
| 39 | @app.route('/auth') |
| 40 | def auth(): |
| 41 | # 取得 Keycloak 回傳的參數並換取 token |
| 42 | token = keycloak.authorize_access_token() |
| 43 | nonce = session.get('nonce') |
| 44 | user_info = keycloak.parse_id_token(token, nonce=nonce) |
| 45 | # 將使用者資訊存入 session,並清除 nonce,避免重複驗證 |
| 46 | session['user'] = user_info |
| 47 | session.pop('nonce', None) |
| 48 | # 重導到乾淨的頁面 |
| 49 | return redirect(url_for('profile')) |
| 50 | |
| 51 | @app.route('/profile') |
| 52 | def profile(): |
| 53 | user_info = session.get('user') |
| 54 | if user_info: |
| 55 | return f"歡迎, {user_info.get('name', '使用者')}!" |
| 56 | return redirect(url_for('homepage')) |
| 57 | |
| 58 | if __name__ == '__main__': |
| 59 | app.run(debug=True) |