sso: implement RS256 JWT signing algo
parent
a57ab99014
commit
576ff1b0ea
|
@ -16,12 +16,22 @@ services:
|
|||
volumes:
|
||||
- .:/usr/src/app
|
||||
environment:
|
||||
- TESTING=1
|
||||
|
||||
- TEMPLATES_AUTO_RELOAD=true
|
||||
- AUTHLIB_INSECURE_TRANSPORT=1
|
||||
|
||||
# Set these to your testing LDAP dn/password
|
||||
- LDAP_BIND_DN
|
||||
- LDAP_BIND_PASSWORD
|
||||
# ...or uncomment this to allow any login with some mocked user info
|
||||
# - TESTING=1
|
||||
|
||||
- LOGGING_LEVEL=DEBUG
|
||||
|
||||
# Uncomment these to enable proper RSA JWT id_tokens signing
|
||||
# - JWT_PRIVATE_KEY=private.pem
|
||||
# - JWT_PUBLIC_KEYS=public.pem,public.pem
|
||||
# - JWT_ALG=RS256
|
||||
|
||||
volumes:
|
||||
pgdata:
|
||||
|
|
|
@ -25,14 +25,6 @@ import logging
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
DUMMY_JWT_CONFIG = {
|
||||
"key": "secret-key",
|
||||
"alg": "HS256",
|
||||
"iss": "https://sso.hackerspace.pl",
|
||||
"exp": 3600,
|
||||
}
|
||||
|
||||
|
||||
def exists_nonce(nonce, req):
|
||||
exists = AuthorizationCode.query.filter_by(
|
||||
client_id=req.client_id, nonce=nonce
|
||||
|
@ -48,7 +40,7 @@ def generate_user_info(user, scope):
|
|||
preferred_username=user.username,
|
||||
nickname=user.username,
|
||||
groups=user.groups,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def create_authorization_code(client, grant_user, request):
|
||||
|
@ -116,7 +108,7 @@ class HybridGrant(_OpenIDHybridGrant):
|
|||
return exists_nonce(nonce, request)
|
||||
|
||||
def get_jwt_config(self):
|
||||
return DUMMY_JWT_CONFIG
|
||||
return app.config.get("JWT_CONFIG")
|
||||
|
||||
def generate_user_info(self, user, scope):
|
||||
return generate_user_info(user, scope)
|
||||
|
|
|
@ -51,9 +51,24 @@ LDAP_BIND_PASSWORD = env.str("LDAP_BIND_PASSWORD", default="insert password here
|
|||
PROXYFIX_ENABLE = env.bool("PROXYFIX_ENABLE", default=True)
|
||||
PROXYFIX_NUM_PROXIES = env.int("PROXYFIX_NUM_PROXIES", default=1)
|
||||
|
||||
import pathlib
|
||||
from authlib.jose import jwk
|
||||
|
||||
jwt_alg = env.str("JWT_ALG", default="HS256")
|
||||
|
||||
if jwt_alg == "HS256":
|
||||
jwt_privkey = env.str("JWT_SECRET_KEY", default=SECRET_KEY)
|
||||
JWT_PUBLIC_KEYS = []
|
||||
else:
|
||||
jwt_privkey = jwk.dumps(env.path("JWT_PRIVATE_KEY").read_text(), kty="RSA")
|
||||
JWT_PUBLIC_KEYS = [
|
||||
jwk.dumps(pathlib.Path(pub).read_text(), kty="RSA")
|
||||
for pub in env.list("JWT_PUBLIC_KEYS")
|
||||
]
|
||||
|
||||
JWT_CONFIG = {
|
||||
"key": env.str("JWT_SECRET_KEY", default=SECRET_KEY),
|
||||
"alg": env.str("JWT_ALG", default="HS256"),
|
||||
"key": jwt_privkey,
|
||||
"alg": jwt_alg,
|
||||
"iss": env.str("JWT_ISS", default="https://sso.hackerspace.pl"),
|
||||
"exp": env.int("JWT_EXP", default=3600),
|
||||
}
|
||||
|
|
|
@ -173,7 +173,6 @@ def authorize():
|
|||
except OAuth2Error as error:
|
||||
return render_template("authorization_error.html", error=dict(error.get_body()))
|
||||
|
||||
print(grant)
|
||||
if grant.client.membership_required and not current_user.is_membership_active:
|
||||
return render_template("membership_required.html")
|
||||
|
||||
|
@ -239,6 +238,11 @@ def api_userinfo():
|
|||
return jsonify(generate_user_info(user, current_token.scope))
|
||||
|
||||
|
||||
@bp.route("/.well-known/jwks.json")
|
||||
def jwks_endpoint():
|
||||
return jsonify({"keys": current_app.config["JWT_PUBLIC_KEYS"]})
|
||||
|
||||
|
||||
@bp.route("/.well-known/openid-configuration")
|
||||
def openid_configuration():
|
||||
return jsonify(
|
||||
|
@ -247,6 +251,7 @@ def openid_configuration():
|
|||
"authorization_endpoint": url_for(".authorize", _external=True),
|
||||
"token_endpoint": url_for(".issue_token", _external=True),
|
||||
"userinfo_endpoint": url_for(".api_userinfo", _external=True),
|
||||
"jwks_uri": url_for(".jwks_endpoint", _external=True),
|
||||
"response_types_supported": ["code", "id_token", "token id_token"],
|
||||
"token_endpoint_auth_methods_supported": [
|
||||
"client_secret_basic",
|
||||
|
|
Loading…
Reference in New Issue