--- title: Configure the Pinniped Concierge to Validate JWT tokens description: Set up JSON Web Token (JWT) based token authentication on an individual Kubernetes cluster. cascade: layout: docs menu: docs: name: Configure Concierge JWT Authentication weight: 30 parent: howtos --- The Concierge can validate [JSON Web Tokens (JWTs)](https://tools.ietf.org/html/rfc7519), which are commonly issued by [OpenID Connect (OIDC)](https://openid.net/connect/) identity providers. This guide shows you how to use this capability _without_ the Pinniped Supervisor. This is most useful if you have only a single cluster and want to authenticate to it via an existing OIDC provider. If you have multiple clusters, you may want to [install]({{< ref "install-supervisor" >}}) and [configure]({{< ref "configure-supervisor" >}}) the Pinniped Supervisor. Then you can [configure the Concierge to use the Supervisor for authentication]({{< ref "configure-concierge-supervisor-jwt" >}}). ## Prerequisites Before starting, you should have the [command-line tool installed]({{< ref "install-cli" >}}) locally and [Concierge running in your cluster]({{< ref "install-concierge" >}}). You should also have some existing OIDC issuer configuration: - An OIDC provider that supports [discovery](https://openid.net/specs/openid-connect-discovery-1_0.html) and the `email` scope. - A public client with callback URI `http://127.0.0.1:12345/callback` and `email` scope. ## Create a JWTAuthenticator Create a JWTAuthenticator describing how to validate tokens from your OIDC issuer: ```yaml apiVersion: authentication.concierge.pinniped.dev/v1alpha1 kind: JWTAuthenticator metadata: name: my-jwt-authenticator spec: issuer: https://my-issuer.example.com/any/path audience: my-client-id claims: username: email ``` If you've saved this into a file `my-jwt-authenticator.yaml`, then install it into your cluster using: ```sh kubectl apply -f my-jwt-authenticator.yaml ``` ## Generate a kubeconfig file Generate a kubeconfig file to target the JWTAuthenticator: ```sh pinniped get kubeconfig \ --oidc-client-id my-client-id \ --oidc-scopes openid,email \ --oidc-listen-port 12345 \ > my-cluster.yaml ``` This creates a kubeconfig YAML file `my-cluster.yaml` that targets your JWTAuthenticator using `pinniped login oidc` as an [ExecCredential plugin](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins). It should look something like below: ```yaml apiVersion: v1 kind: Config current-context: pinniped clusters: - cluster: certificate-authority-data: LS0tLS[...] server: https://my-kubernetes-api-endpoint.example.com:59986 name: pinniped contexts: - context: cluster: pinniped user: pinniped name: pinniped users: - name: pinniped user: exec: apiVersion: client.authentication.k8s.io/v1beta1 command: /usr/local/bin/pinniped args: - login - oidc - --enable-concierge - --concierge-api-group-suffix=pinniped.dev - --concierge-authenticator-name=my-jwt-authenticator - --concierge-authenticator-type=jwt - --concierge-endpoint=https://my-kubernetes-api-endpoint.example.com:59986 - --concierge-ca-bundle-data=LS0tLS[...] - --issuer=https://my-oidc-issuer.example.com/any/path - --client-id=my-client-id - --scopes=offline_access,openid,email - --listen-port=12345 - --request-audience=my-client-id ``` ## Use the kubeconfig file Use the kubeconfig with `kubectl` to access your cluster: ```sh kubectl --kubeconfig my-cluster.yaml get namespaces ``` You should see: - The `pinniped login oidc` command is executed automatically by `kubectl`. - Pinniped opens your browser window and directs you to login with your identity provider. - After you've logged in, you see a page telling you `you have been logged in and may now close this tab`. - In your shell, you see your clusters namespaces. If instead you get an access denied error, you may need to create a ClusterRoleBinding for the `email` of your OIDC account, for example: ```sh kubectl create clusterrolebinding my-user-admin \ --clusterrole edit \ --user my-username@example.com ``` ## Other notes - Pinniped kubeconfig files do not contain secrets and are safe to share between users. - Temporary OIDC session credentials such as ID, access, and refresh tokens are stored in: - `~/.config/pinniped/sessions.yaml` (macOS/Linux) - `%USERPROFILE%/.config/pinniped/sessions.yaml` (Windows). - If your OIDC provider supports [wildcard port number matching](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-16#section-2.1) for localhost URIs, you can omit the `--oidc-listen-port` flag to use a randomly chosen ephemeral TCP port. - The Pinniped command-line tool can only act as a public client with no client secret. If your provider only supports non-public clients, consider using the Pinniped Supervisor. - In general, it is not safe to use the same OIDC client across multiple clusters. If you need to access multiple clusters, please [install the Pinniped Supervisor]({{< ref "install-supervisor" >}}).