pyobs-auth 2.0.0.dev7__tar.gz → 2.0.0.dev9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyobs-auth
3
- Version: 2.0.0.dev7
3
+ Version: 2.0.0.dev9
4
4
  Summary: Shared Keycloak/OIDC authentication client for pyobs web services
5
5
  Author-email: Tim-Oliver Husser <thusser@uni-goettingen.de>
6
6
  License-Expression: MIT
@@ -42,7 +42,9 @@ class KeycloakClient:
42
42
  def _discovery(self):
43
43
  return fetch_discovery_document(self._settings.discovery_url)
44
44
 
45
- def start_authorization(self, *, redirect_uri: str | None = None) -> AuthorizationRequest:
45
+ def start_authorization(
46
+ self, *, idp_hint: str | None = None, redirect_uri: str | None = None
47
+ ) -> AuthorizationRequest:
46
48
  """Build the redirect URL for the authorization-code + PKCE login flow."""
47
49
  document = self._discovery()
48
50
  state = _b64url(secrets.token_bytes(24))
@@ -62,6 +64,10 @@ class KeycloakClient:
62
64
  "code_challenge": code_challenge,
63
65
  "code_challenge_method": "S256",
64
66
  }
67
+ if idp_hint:
68
+ # kc_idp_hint: Keycloak skips its login/IdP-selection page and redirects straight to
69
+ # that identity provider; unknown aliases fall back to the normal login page.
70
+ params["kc_idp_hint"] = idp_hint
65
71
  url = f"{document.authorization_endpoint}?{urlencode(params)}"
66
72
  return AuthorizationRequest(url=url, state=state, code_verifier=code_verifier)
67
73
 
@@ -33,6 +33,7 @@ class KeycloakSettings:
33
33
  post_logout_redirect_uri: str | None = None
34
34
  scopes: tuple[str, ...] = field(default_factory=lambda: ("openid", "profile", "email"))
35
35
  user_resolver: str | None = None
36
+ idp_hint: str | None = None
36
37
 
37
38
  @property
38
39
  def issuer(self) -> str:
@@ -85,4 +86,5 @@ def get_settings() -> KeycloakSettings:
85
86
  post_logout_redirect_uri=raw.get("POST_LOGOUT_REDIRECT_URI"),
86
87
  scopes=tuple(raw.get("SCOPES", ("openid", "profile", "email"))),
87
88
  user_resolver=raw.get("USER_RESOLVER"),
89
+ idp_hint=raw.get("IDP_HINT"),
88
90
  )
@@ -37,7 +37,12 @@ class LoginView(View):
37
37
  def get(self, request: HttpRequest) -> HttpResponse:
38
38
  settings = get_settings()
39
39
  client = KeycloakClient(settings)
40
- authorization = client.start_authorization()
40
+ # ?idp_hint= handling: absent -> the configured default hint (fast path); present but
41
+ # empty -> no hint (local Keycloak account); any value -> that specific hint.
42
+ idp_hint = request.GET.get("idp_hint")
43
+ if idp_hint is None:
44
+ idp_hint = settings.idp_hint
45
+ authorization = client.start_authorization(idp_hint=idp_hint or None)
41
46
 
42
47
  request.session[SESSION_STATE_KEY] = authorization.state
43
48
  request.session[SESSION_CODE_VERIFIER_KEY] = authorization.code_verifier
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyobs-auth"
3
- version = "2.0.0.dev7"
3
+ version = "2.0.0.dev9"
4
4
  description = "Shared Keycloak/OIDC authentication client for pyobs web services"
5
5
  authors = [{ name = "Tim-Oliver Husser", email = "thusser@uni-goettingen.de" }]
6
6
  requires-python = ">=3.11"
File without changes