Cognito User Pools are different from, but related to, Federated Identity Pools. User pools give you an id token and an access token, while identity pools give you an access key, a secret key, and a session token. A user pool can be split into user groups, each of which can be assigned an IAM role, but a member of a user doesn't need an IAM role, they only have one if you put them in a group, also they can belong to multiple groups, which you can optionally assign numbers to, and a user will assume the role of the group they belong to that has the lowest number, except members of user pools never actually assume a role unless their user pool credentials are used to obtain identity pool credentials. Identity pools can only have two roles, one for authenticated user and one for unauthenticated users. So regardless of what role is configured for a user pool group, members of that groups will assume the role for the authenticated users of the identity pool, unless you configure the identity pool to prefer the roles indicated in the user's id token. In order to get identity pool creds using a user pool, the identity pool needs to be configured to accept the user pool as an authentication provider. In order for an identity pool to get a role from the user's id token, the role in the id token must have a trust relationship with the identity pool, it will be configured by default to have a trust relationship with it's own user pool, so you need to change it to trust the identity pool instead.
Now you can access AWS resources with the one of many roles. One resource that makes sense to access is API Gateway, where API resources can now be restricted based on IAM roles. However, it's important to remember that when an API resource invokes a Lambda, the Lambda context users the role of the API Gateway resource, not the role of the user invoking the resource, unless you configure the resource to invoke with the calling role instead. If you don't want to user IAM roles to restrict API access, or if you don't want to use identity pools, user pools can be used directly in API Gateway, even though you cannot use user pools for any other AWS service. API resources can be restricted by either custom authenticators (the original solution) or with a user pool authorizer. If you user the user pool authorizer, make sure to override the “Authorization” header in the API Gateway generated SDK, because the generated SDK is not aware of authorizers. Despite the fact that user pools are divided into groups, the user pool authorizer is unaware of any groups and simply gives you on/off access to the API. I came to this understanding after much struggle on my own and it was confirmed by a random comment on a forum somewhere, I sure didn't learn it anywhere in the AWS documentation. However, if you use the user pool authenticators, you can define OAuth scopes and create a resource server, I started to learn about this path, but I couldn't read through my tears and I gave up, but based on a circular dependency of links in the documentation, I got the impression that defining OAuth scopes might involve creating custom authorizers, so if it's that true I think I'd just use custom authorizers in the first place and avoid learning five more pages of incomprehensible jargon.
Anyway, I have a thing that works now and I have some easy to read code that makes clear one way to get things done (apparently there at least a dozen other ways to do it).
If you want to read more, subscribe to my personal newsletter.