3

I'm using Cognito App Client integration with external provider(Twitch) User authentication works fine, but as code from auth server is consumed by Cognito, I'm not sure how should I send Twitch requests with token, which I'd normally get from twitch I Cognito wouldn't consume this code. I only have Cognito code, which I can use in https://{my-domain}/oauth2/token requests in exchange for Cognito tokens. request returns id_token, access_token and refresh_token, which decoded look like id token

{
  "at_hash": "yTNkeTAqzqcXCYi3yLL2Pw",
  "sub": "3cfba641-4058-475f-9818-17291175fd31",
  "cognito:groups": [
    "us-east-1_xxxxxxxxxxxx"
  ],
  "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxxxxx",
  "cognito:username": "xxxxxxxxxxxx",
  "preferred_username": "xxxxxxxxxxxx",
  "nonce": "SxxlipCDVbXbcXa1H7Uf9_nM0uOurAAObUVCyreBDDux99QoAngUoiGdE0me-0Zon6fEVLLTSqD4EN1Y6_lFm48MaoBaxyywZCQKOT70gfQEfkuhlsjImJd1ko3qH3QKdlmvWSPCUZoACPYNSgR364VPELyQTVMkRTCt9eYROag",
  "aud": "35l1cn53cnj9sv1ndu8u01amk0",
  "identities": [
    {
      "userId": "xxxxxxxxxxxx",
      "providerName": "xxxxxxxxxxxx",
      "providerType": "OIDC",
      "issuer": null,
      "primary": "true",
      "dateCreated": "1588191000072"
    }
  ],
  "token_use": "id",
  "auth_time": 1588191003,
  "exp": 1588194603,
  "iat": 1588191003
}

access token

{
  "sub": "3cfba641-4058-475f-9818-17291175fd31",
  "cognito:groups": [
    "us-east-1_xxxxxxxxxxxx"
  ],
  "token_use": "access",
  "scope": "aws.cognito.signin.user.admin phone openid profile email",
  "auth_time": 1588191003,
  "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_xxxxxxxxxxxx",
  "exp": 1588194603,
  "iat": 1588191003,
  "version": 2,
  "jti": "55863213-c764-4b07-a386-a9c93d14e4b2",
  "client_id": "xxxxxxxxxxxx",
  "username": "xxxxxxxxxxxx"
}

How can I get user token to call Twitch API (for example GET https://api.twitch.tv/helix/users endpoint with authorized user's token)

Piekarski D
  • 377
  • 1
  • 4
  • 15
  • You use the id_token as Authorization header for your call to TwitchAPI. – Nghia Do Apr 30 '20 at 10:48
  • @NghiaDo no, id tokens aren't used for authorization. anyways, I've tried it. response from twitch is same as when I try use access_token - `"Must provide a valid Client-ID or OAuth token"` – Piekarski D Apr 30 '20 at 13:59
  • That is correct. Please use id-token is for OAuth token – Nghia Do Apr 30 '20 at 14:25
  • @NghiaDo you totally mix up the concepts. client id, is client id which i get for twitch application(it's used when I try to query users by their ids) – Piekarski D Apr 30 '20 at 14:28
  • @NghiaDo plus I've already tried using both access_token and id_token for Auth header – Piekarski D Apr 30 '20 at 14:30
  • @NghiaDo I've already used same endpoint for last half a year with standard twitch oauth token(not Cognito's OIDC), and I used access_token for that – Piekarski D Apr 30 '20 at 14:31

1 Answers1

2

CAUTION - Doing it incorrectly, you expose sensitive attributes to client.

You need to create 2 versions of attributes - custom and dev:custom, map oidc provider attributes to custom ones (looks like dev:custom aren't mappable), then in TokenGeneration_HostedAuth trigger you need to get these custom attributes, set dev:custom ones, then delete customs.

Seems like a tweak, but I don't see another way of doing it and keeping tokens safe.

Solution for that is to create custom attributes in your user pool, then map these attributes for identity provider. Looks something like:

'custom:refresh_token': refresh_token
'custom:id_token': id_token
'custom:access_token': access_token

Cloudformation template for that:

user pool

....
Schema: [
    {
        AttributeDataType: 'String',
        DeveloperOnlyAttribute: true,
        Mutable: true,
        Name: 'refresh_token',
        Required: false,
    },
    {
        AttributeDataType: 'String',
        DeveloperOnlyAttribute: true,
        Mutable: true,
        Name: 'access_token',
        Required: false,
    },
    {
        AttributeDataType: 'String',
        DeveloperOnlyAttribute: true,
        Mutable: true,
        Name: 'id_token',
        Required: false,
    },
    {
        AttributeDataType: 'String',
        Mutable: true,
        Name: 'refresh_token',
        Required: false,
    },
    {
        AttributeDataType: 'String',
        Mutable: true,
        Name: 'access_token',
        Required: false,
    },
    {
        AttributeDataType: 'String',
        Mutable: true,
        Name: 'id_token',
        Required: false,
    },
],
....

user pool identity provider

....
AttributeMapping: {
    'custom:refresh_token': 'refresh_token',
    'custom:access_token': 'access_token',
    'custom:id_token': 'id_token',
},
....
Piekarski D
  • 377
  • 1
  • 4
  • 15
  • Are you saying that you were ultimately able to authenticate with the Twitch API using your access_token from the Cognito token exchange? I am at this stage now and have my access_token after a succesful login, but when I send it to Twitch as my Auth Bearer token I get "Invalid OAuth Token" – Rohan Sep 03 '20 at 05:12
  • @Rohan I'm not sure if we're talking about the same cases. Please describe what you're trying to solve and I'll probably know how to help you, as I'm working with Twitch API for pretty long time yet – Piekarski D Sep 03 '20 at 12:36
  • In your original post here your problem was that you could not get back a Twitch access_token when using AWS Cognito. In the comments you were told to use the access_token that you get back from AWS, but this is not working for me. – Rohan Sep 03 '20 at 22:52
  • actually comments aren't touching my issue. by my previous comment I just wanted to make sure you're using Cognito OIDC – Piekarski D Sep 04 '20 at 14:02
  • Yes, using Cognito OIDC, when I receive an access_token back from AWS it is not a twitch access_code and so I cannot interact with the twitch API on the users behalf. – Rohan Sep 07 '20 at 00:46
  • @Rohan where do you receive it? I get mine in `TokenGeneration_HostedAuth` lambda trigger(but I needed to map attributes for Identity Provider - take a look at what's written about custom attributes in accepted solution), then save it to user attributes(pay attention to make these attributes accessible only from server) – Piekarski D Sep 07 '20 at 12:46
  • Ok I will look deeper into the triggers. Can you provide a code example of your Lambda at all? – Rohan Sep 07 '20 at 23:32
  • I also can't find that trigger for Cognito, all I can see is PreTokenGeneration – Rohan Sep 08 '20 at 00:20
  • @Rohan I don't remember which exactly trigger was that, but I have `PostConfirmation`, `PreSignUp`, `CustomMessage`, `PreTokenGeneration`, `DefineAuthChallenge` on my stack – Piekarski D Sep 08 '20 at 16:25
  • and in nutshell it looks like(JS) `export default async (event) => { const { request: { userAttributes }, userName: username } = event const { 'custom:access_token': accessToken } = userAttributes }` – Piekarski D Sep 08 '20 at 16:26
  • Two years later I can confirm that this approach works. Thanks @PiekarskiD ! One thing to note is that I needed to edit the attribute read/write permissions for my app client so that the custom token attributes are writable. – worsnupd Aug 20 '22 at 02:24