4
votes

I'm providing an external-facing REST GET API service in a kubernetes pod on AWS EKS. I had configured an ALB Ingress for this service which enforces Cognito user pool authentication. Cognito is configured with Authorization code grant with the openid OAuth scope enabled.

If I invoke my REST API from the browser, I get redirected to the Cognito login page. After a sucessful authentication on the form here, I can access my REST GET API just fine. This works, but this is not what I'd like to achieve.

Instead of this, I would need to use a Bearer token, after getting successfully authenticated. So first I invoke https://cognito-idp.ap-southeast-1.amazonaws.com using Postman with the request:

    "AuthParameters" : {
        "USERNAME" : "<email>",
        "PASSWORD" : "<mypass>",
        "SECRET_HASH" : "<correctly calculated hash>"
    },
    "AuthFlow" : "USER_PASSWORD_AUTH",
    "ClientId" : "<cognito user pool id>"
}

and I get a successful response like:

  "AuthenticationResult": {
    "AccessToken": "...",
    "ExpiresIn": 3600,
    "IdToken": "...",
    "RefreshToken": "...",
    "TokenType": "Bearer"
  },
  "ChallengeParameters": {}
}

In the last step I'm trying to invoke my REST API service passing the Authorization HTTP header with the value Bearer <AccessToken> but I still get a HTML response with the login page.

How can I configure Cognito to accept my Bearer token for this call as an authenticated identity?

2
Try using IdToken instead of AccessTokenStargazer
I tried to use Bearer <IdToken> and IdToken as well as the value of the Authorization header, but nevertheless, I get http 200 OK and an HTML response with the login page.Kristof Jozsa
In the case of browser authentication (via a Cognito hosted page) where you can successfully access the API, how is the token passed to the API?Max Ivanov
the Cognito form login response sets a cookie to the browser and the next GET request authenticates sending the AWSELBAuthSessionCookie..Kristof Jozsa

2 Answers

0
votes

Quoting AWS support on this topic: "the Bearer token can not be used instead of the session cookie because in a flow involving bearer token would lead to generating the session cookie".

So unfortunately this usecase is not possible to implemented as of today.

0
votes

STANDARD BEHAVIOUR

I would aim for a standard solution, which works like this:

  • API returns data when it receives a valid access token, or a 401 if the token is missing, invalid or expired - the API never redirects the caller

  • UIs do their own redirects to the Authorization Server when there is no token yet or when a 401 is received from the API

If it helps, my OAuth Message Workflow blog post demonstrates the 3 legged behaviour between UI, API and Authorization Server.

API GATEWAY PATTERN

It is perfectly fine to use an API Gateway Design Pattern, where token validation is done via middleware before hitting your API.

However that middleware must return a 401 when tokens are rejected rather than redirecting the API client.

IMPACT OF APIs REDIRECTING THE CLIENT

This may just about work for web UIs, though user experience will be limited since the UI will have no opportunity to save the user's data or location before redirecting.

For mobile / desktop apps it is more problematic, since the UI must redirect using the system browser rather than a normal UI view - see the screenshots on my Quick Start Page.

CHOICES

Any of these solutions would be fine:

  • Possibly the middleware you are using can be configured differently to behave like a proper API Gateway?

  • Or perhaps you could look for alternative middleware that does token validation, such as an AWS Lambda custom authorizer?

  • Or do the OAuth work in the API's code, as in this Sample API of mine

MY PREFERENCE

Sometimes I prefer to write code to do the OAuth work, since it can provide better extensibility when dealing with custom claims. My API Authorization blog post has some further info on this.