baptistegh commented on code in PR #75913:
URL: https://github.com/apache/airflow/pull/75913#discussion_r4413682493
##########
providers/keycloak/src/airflow/providers/keycloak/auth_manager/services/token.py:
##########
@@ -210,3 +257,66 @@ def create_client_credentials_token(
)
return get_auth_manager().generate_api_jwt(user,
expiration_time_in_seconds=expiration_time_in_seconds)
+
+
+def create_token_from_authorization_code(
+ code: str,
+ code_verifier: str,
+ redirect_uri: str,
+ expiration_time_in_seconds: int = conf.getint("api_auth",
"jwt_cli_expiration_time"),
+) -> str:
+ """
+ Create a CLI token from an authorization code obtained through
``/login/cli``.
+
+ Keycloak checks ``code_verifier`` against the challenge ``/login/cli``
forwarded, so
+ the code is useless to anyone who intercepted it on the loopback redirect.
+ """
+ if not is_cli_authorization_code_enabled():
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail="The authorization_code grant is not enabled for
command-line clients",
+ )
+ if not is_cli_loopback_redirect_uri(redirect_uri):
+ raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid redirect_uri")
+
+ client = KeycloakAuthManager.get_keycloak_client()
+ try:
+ tokens = client.token(
+ grant_type="authorization_code",
+ code=code,
+ redirect_uri=redirect_uri,
+ code_verifier=code_verifier,
+ scope="openid",
+ )
+ except KeycloakError:
+ raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid authorization code")
+
+ return _create_api_jwt_from_keycloak_tokens(client, tokens,
expiration_time_in_seconds)
+
+
+def refresh_cli_token(token: str) -> str:
+ """
+ Create a CLI token with fresh Keycloak tokens from a CLI token that is
still valid.
+
+ The new token expires with the old one, so refreshing never extends a CLI
session.
+ Expired and revoked tokens are refused by ``get_user_from_token``.
+ """
+ auth_manager = get_auth_manager()
+ try:
+ user = cast("KeycloakAuthManagerUser | None",
async_to_sync(auth_manager.get_user_from_token)(token))
+ except jwt.PyJWTError:
+ user = None
+ if not user or not user.refresh_token:
+ raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid token")
+
+ client = KeycloakAuthManager.get_keycloak_client()
+ try:
+ tokens = client.refresh_token(user.refresh_token)
+ except KeycloakError:
+ raise HTTPException(status_code=status.HTTP_403_FORBIDDEN,
detail="Invalid token")
+
+ user.access_token = tokens["access_token"]
+ user.refresh_token = tokens["refresh_token"]
Review Comment:
On not advertising the grant at all: I don't see how Airflow can know up
front. Nothing in `[keycloak_auth_manager]` tells us whether the client has
"Use Refresh Tokens" on, and we only learn it when a refresh comes back empty.
The options I see are a config flag the deployment manager sets, or leaving it
with the clearer error.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]