openid-connectaws-alb

How can my EKS web application retrieve the current user authenticated by AWS ALB through OKTA OIDC


I'm working with a web application deployed on Amazon Elastic Kubernetes Service (EKS). The user authentication is done through Okta. That all works fine but if I'm logged in, I want the web application to show my name, that is, the name of the current user.

There's a blog post that closely describes the type of setup that I have, which was also done through Terraform. So far, my online searches for this have led me to answers on how to setup the authentication (which is already done) not on how to get the current user.

My basic understanding is this: the original request goes to the Application Load Balancer (ALB) with handles the authentication with Okta. The end result is a session cookie, that the application sends via the browser with future requests, so that they end up on the target IP where the backend can respond. This is the relevant text on the authentication flow from the AWS documentation:

"After the load balancer validates the ID token, it exchanges the access token with the IdP user info endpoint to get the user claims.

The load balancer creates the authentication session cookie and sends it to the client so that the client's user agent can send the cookie to the load balancer when making requests."

I can see from the load balancer listener rules that there is a user info endpoint: https://myorg.okta.com/oauth2/v1/userinfo but can the client application use it to retrieve the user details, and if so, how? I tried to curl it with the session cookie but got a 400 error.

There is also an API documented on the Okta site that "Fetches the current user linked to API token or session cookie":

curl -v -X GET \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "Authorization: SSWS ${api_token}" \
"https://${yourOktaDomain}/api/v1/users/me"

I don't have an API token so I tried using the AWSELBAuthSessionCookie instead but got:

{"errorCode":"E0000011","errorSummary":"Invalid token provided","errorLink":"E0000011","errorId":"oaeRNui7fSPQIq_LWuGro5EbV","errorCauses":[]}

Any answer with a summary of steps and links to relevant documentation would be great. Thank you.


Solution

  • The user info is always sent to the application (the target) by the ALB in a header with every request from the client, so the back-end will need to process it and somehow make it available to the front-end. Probably the simplest would be to include it with the response.

    The answer is actually further down in the documentation about user claims:

    After your load balancer authenticates a user successfully, it sends the user claims received from the IdP to the target. The load balancer signs the user claim so that applications can verify the signature and verify that the claims were sent by the load balancer.

    The load balancer adds the following HTTP headers:

    x-amzn-oidc-accesstoken The access token from the token endpoint, in plain text.

    x-amzn-oidc-identity The subject field (sub) from the user info endpoint, in plain text.

    x-amzn-oidc-data The user claims, in JSON web tokens (JWT) format.

    The last header is exactly what I need. It has all the user info, Base64 encoded. Worth noting that I had grepped the logs for x-amzn-oidc-data and got nothing. But after doing a case insensitive search by piping the request logs to grep -i x-amzn-oidc-data I found lots of entries with the X-Amzn-Oidc-Data header.

    By the way, I use mitmproxy to log every request to the application, including headers, turned out to be very useful in finding this solution!