MCPcopy Create free account
hub / github.com/feast-dev/feast / OidcTokenParser

Class OidcTokenParser

sdk/python/feast/permissions/auth/oidc_token_parser.py:23–265  ·  view source on GitHub ↗

A ``TokenParser`` to use an OIDC server to retrieve the user details. Server settings are retrieved from the ``auth`` configuration of the Feature store. Incoming tokens that contain a ``kubernetes.io`` claim (i.e. Kubernetes service-account tokens) are handled via a lightweight To

Source from the content-addressed store, hash-verified

21
22
23class OidcTokenParser(TokenParser):
24 """
25 A ``TokenParser`` to use an OIDC server to retrieve the user details.
26 Server settings are retrieved from the ``auth`` configuration of the Feature store.
27
28 Incoming tokens that contain a ``kubernetes.io`` claim (i.e. Kubernetes
29 service-account tokens) are handled via a lightweight TokenReview that
30 extracts only the namespace — no RBAC queries needed. All other tokens
31 follow the standard OIDC/Keycloak JWKS validation path.
32 """
33
34 _auth_config: OidcAuthConfig
35
36 def __init__(self, auth_config: OidcAuthConfig):
37 self._auth_config = auth_config
38 self.oidc_discovery_service = OIDCDiscoveryService(
39 self._auth_config.auth_discovery_url,
40 verify_ssl=self._auth_config.verify_ssl,
41 ca_cert_path=self._auth_config.ca_cert_path,
42 )
43 self._k8s_auth_api = None
44
45 async def _validate_token(self, access_token: str):
46 """
47 Validate the token extracted from the header of the user request against the OAuth2 server.
48 """
49 # FastAPI's OAuth2AuthorizationCodeBearer requires a Request type but actually uses only the headers field
50 # https://github.com/tiangolo/fastapi/blob/eca465f4c96acc5f6a22e92fd2211675ca8a20c8/fastapi/security/oauth2.py#L380
51 request = Mock(spec=Request)
52 request.headers = {"Authorization": f"Bearer {access_token}"}
53
54 oauth_2_scheme = OAuth2AuthorizationCodeBearer(
55 tokenUrl=self.oidc_discovery_service.get_token_url(),
56 authorizationUrl=self.oidc_discovery_service.get_authorization_url(),
57 refreshUrl=self.oidc_discovery_service.get_refresh_url(),
58 )
59
60 await oauth_2_scheme(request=request)
61
62 @staticmethod
63 def _extract_username_or_raise_error(data: dict) -> str:
64 """Extract the username from the decoded JWT. Raises if missing — identity is mandatory.
65
66 Checks ``preferred_username`` first (Keycloak default), then falls back
67 to ``upn`` (Azure AD / Entra ID).
68 """
69 if "preferred_username" in data:
70 return data["preferred_username"]
71 if "upn" in data:
72 return data["upn"]
73 raise AuthenticationError(
74 "Missing preferred_username or upn field in access token."
75 )
76
77 @staticmethod
78 def _extract_claim(data: dict, *keys: str, expected_type: type = list):
79 """Walk *keys* into *data* and return the leaf value, or ``expected_type()`` if any key is missing or the wrong type."""
80 node = data

Calls

no outgoing calls