amplify-js
amplify-js copied to clipboard
Unauthorized errors: Cognito user pool as generic OIDC provider
Before opening, please confirm:
- [X] I have searched for duplicate or closed issues and discussions.
- [X] I have read the guide for submitting bug reports.
- [X] I have done my best to include a minimal, self-contained set of instructions for consistently reproducing the issue.
JavaScript Framework
React
Amplify APIs
Authentication, GraphQL API, DataStore
Amplify Version
v6
Amplify Categories
auth, api
Backend
Amplify CLI
Environment information
# Put output below this line
System:
OS: macOS 14.2.1
CPU: (8) arm64 Apple M1
Memory: 53.77 MB / 8.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.4.0 - ~/.local/share/nvm/v20.4.0/bin/node
npm: 9.7.2 - ~/.local/share/nvm/v20.4.0/bin/npm
Browsers:
Brave Browser: 114.1.52.130
Chrome: 121.0.6167.160
Safari: 17.2.1
npmPackages:
@aws-amplify/ui-react: ^6.1.0 => 6.1.0
@aws-amplify/ui-react-internal: undefined ()
@capacitor/app: 5.0.6 => 5.0.6
@capacitor/cli: 5.6.0 => 5.6.0
@capacitor/core: 5.6.0 => 5.6.0
@capacitor/haptics: 5.0.6 => 5.0.6
@capacitor/keyboard: 5.0.7 => 5.0.7
@capacitor/status-bar: 5.0.6 => 5.0.6
@cypress/angular: 0.0.0-development
@cypress/mount-utils: 0.0.0-development
@cypress/react: 0.0.0-development
@cypress/react18: 0.0.0-development
@cypress/svelte: 0.0.0-development
@cypress/vue: 0.0.0-development
@cypress/vue2: 0.0.0-development
@ionic-enterprise/auth: ^5.1.3 => 5.1.3
@ionic-enterprise/identity-vault: ^5.12.2 => 5.12.2
@ionic/react: ^7.0.0 => 7.6.4
@ionic/react-router: ^7.0.0 => 7.6.4
@testing-library/dom: >=7.21.4 => 9.3.4
@testing-library/jest-dom: ^5.16.5 => 5.17.0
@testing-library/react: ^14.0.0 => 14.1.2
@testing-library/user-event: ^14.4.3 => 14.5.2
@types/react: ^18.0.27 => 18.2.47
@types/react-dom: ^18.0.10 => 18.2.18
@types/react-router: ^5.1.20 => 5.1.20
@types/react-router-dom: ^5.3.3 => 5.3.3
@vitejs/plugin-legacy: ^5.0.0 => 5.2.0
@vitejs/plugin-react: ^4.0.1 => 4.2.1
aws-amplify: ^6.0.11 => 6.0.11
aws-amplify/adapter-core: undefined ()
aws-amplify/analytics: undefined ()
aws-amplify/analytics/kinesis: undefined ()
aws-amplify/analytics/kinesis-firehose: undefined ()
aws-amplify/analytics/personalize: undefined ()
aws-amplify/analytics/pinpoint: undefined ()
aws-amplify/api: undefined ()
aws-amplify/api/server: undefined ()
aws-amplify/auth: undefined ()
aws-amplify/auth/cognito: undefined ()
aws-amplify/auth/cognito/server: undefined ()
aws-amplify/auth/enable-oauth-listener: undefined ()
aws-amplify/auth/server: undefined ()
aws-amplify/datastore: undefined ()
aws-amplify/in-app-messaging: undefined ()
aws-amplify/in-app-messaging/pinpoint: undefined ()
aws-amplify/push-notifications: undefined ()
aws-amplify/push-notifications/pinpoint: undefined ()
aws-amplify/storage: undefined ()
aws-amplify/storage/s3: undefined ()
aws-amplify/storage/s3/server: undefined ()
aws-amplify/storage/server: undefined ()
aws-amplify/utils: undefined ()
bin: 1.0.0
cypress: ^13.5.0 => 13.6.2
dist: 1.0.0
eslint: ^8.35.0 => 8.56.0
eslint-plugin-react: ^7.32.2 => 7.33.2
ionicons: ^7.0.0 => 7.2.2
ionicons-loader: undefined ()
ionicons/components: undefined ()
ionicons/icons: 7.2.2
jsdom: ^22.1.0 => 22.1.0
react: ^18.2.0 => 18.2.0
react-dom: ^18.2.0 => 18.2.0
react-router: ^5.3.4 => 5.3.4
react-router-dom: ^5.3.4 => 5.3.4
terser: ^5.4.0 => 5.26.0
typescript: ^5.1.6 => 5.3.3
vite: ^5.0.0 => 5.0.11
vitest: ^0.34.6 => 0.34.6
npmGlobalPackages:
@aws-amplify/cli: 12.10.1
corepack: 0.19.0
ionic: 5.4.16
npm: 9.7.2
prettier: 3.0.0
Describe the bug
I have followed the docs here for creating an OIDC owner auth rule against my model: https://docs.amplify.aws/react/build-a-backend/more-features/datastore/authz-rules-setup/#owner-based-authorization-with-oidc-provider. We are using Cognito (user pool) as a generic OIDC provider and I have entered relevant details by running "amplify api update".
The full schema is here:
type User
@model
@auth(rules: [
{ allow: owner, provider: oidc, identityClaim: "sub" }
]) {
username: String!
favourites: [Int]
owner: String
}
I have ruled out there being any issues in how data is created/read/updated by also trying this auth rule in addition to the owner one:
{ allow: private, operations: [create, read, update] }
When this rule is in place everything works fine except that any user can potentially gain access to another user's data.
To highlight that issue I'm having is to do with the owner (oidc) auth rule I have been advised by someone on the Amplify discord to try running queries in ApSync with the appropriate JWT token and this does not result in any 401 errors. However any query I try to run results in unauthorized errors.
e.g.
query MyQuery {
getUser(id: "ce6710aa-f9e2-46a7-bf7b-03b8780b1568") {
id
username
}
}
Returns:
{
"data": {
"getUser": null
},
"errors": [
{
"path": [
"getUser"
],
"data": null,
"errorType": "Unauthorized",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Not Authorized to access getUser on type Query"
}
]
}
So what am I missing from my schema to make queries, mutations and subscriptions work?
I have also tried using "private" instead of "owner" like so:
{ allow: private, provider: oidc, identityClaim: "sub", operations: [create, read, update] }
Thanks
Expected behavior
AppSync does not produce unauthorized errors as if I had used the private auth rule with all operations granted.
Reproduction steps
- Set up Cognito user pool so that it can be connected to as OIDC provider
- Run
amplify api updateand enter details. e.g. Issuer URL, Client id etc. - Use schema similar to above.
- Attempt to run queries in AppSync with JWT token in Authorization field
Code Snippet
// Put your code below this line.
Log output
// Put your logs below this line
aws-exports.js
/* eslint-disable */
// WARNING: DO NOT EDIT. This file is automatically generated by AWS Amplify. It will be overwritten.
const awsmobile = {
"aws_project_region": "eu-west-1",
"aws_cognito_identity_pool_id": "eu-west-1:03223797-8f4a-4667-bc1f-b77a463b3c19",
"aws_cognito_region": "eu-west-1",
"aws_user_pools_id": "eu-west-1_X6oCcM1Bw",
"aws_user_pools_web_client_id": "49t856q7emfn8av69883e0cuo4",
"oauth": {},
"aws_cognito_username_attributes": [
"EMAIL"
],
"aws_cognito_social_providers": [],
"aws_cognito_signup_attributes": [
"EMAIL"
],
"aws_cognito_mfa_configuration": "OFF",
"aws_cognito_mfa_types": [
"SMS"
],
"aws_cognito_password_protection_settings": {
"passwordPolicyMinLength": 8,
"passwordPolicyCharacters": []
},
"aws_cognito_verification_mechanisms": [
"EMAIL"
],
"aws_appsync_graphqlEndpoint": "https://tq74h7r43zaxdk2q5al4nczopu.appsync-api.eu-west-1.amazonaws.com/graphql",
"aws_appsync_region": "eu-west-1",
"aws_appsync_authenticationType": "OPENID_CONNECT"
};
export default awsmobile;
Manual configuration
No response
Additional configuration
No response
Mobile Device
No response
Mobile Operating System
No response
Mobile Browser
No response
Mobile Browser Version
No response
Additional information and screenshots
No response
By the way we are using a custom token provider as outlined here (even though the token comes from Cognito): https://docs.amplify.aws/javascript/build-a-backend/auth/advanced-workflows/#custom-token-providers
@mikejw, can you try to update your auth rules to be the following and see if there is any change in behavior:
type User
@model
@auth(rules: [
{ allow: owner, provider: oidc, identityClaim: "sub::username" }
]) {
username: String!
favourites: [Int]
owner: String
}
I'm still getting this kind of response from the graphql endpoint. NB: This is for path syncUsers, createUser and updateUser.
{
"data": {
"syncUsers": null
},
"errors": [
{
"path": [
"syncUsers"
],
"data": null,
"errorType": "Unauthorized",
"errorInfo": null,
"locations": [
{
"line": 2,
"column": 3,
"sourceName": null
}
],
"message": "Not Authorized to access syncUsers on type Query"
}
]
}
BTW, this is whether or not a explicitly define the "owner" field or not in the schema.
@mikejw sorry, the owner field is inconsequential. The important bit of the change we suggested was the format of the identity claim.
Did you change it to this in the auth rule?
identityClaim: "sub::username"
Oh, you did mention that the same token before the change worked in the AppSync console though... so that's strange.
Can you check the network activity in the browser and see if the syncUser request has an Authorization header with the token you'd expect?
Hey @chrisbonifacio, yep I tried using that new identityClaim value and it didn't seem to help.
Yep, I'm using a custom token provider to make sure the authorization can happen. In AppSync I don't see any 401 unless I modify the token value with arbitrary text.
Hmm, I'm having a hard time reproducing this myself. Can you check the owner field of a record that was created using the token and identityClaim? How is it formatted? The value of owner just has to match the value of the claim on the token.
Amplify GraphQL API's @auth directive and owner rule supports Cognito out of the box. Is there a reason why you have to use Cognito as an OIDC provider instead of a user pool?
Hey @chrisbonifacio I'm trying to look for the data stored in DynamoDB but it shows as empty for some reason. I'm pretty sure I have seen data stored in the owner field as just the user ids that should correspond to user::sub. e.g. '562d4a8f-0a58-45fb-a873-6014759b6745'
We want to use Ionic Auth Connect and Vault components to secure the token on device with biometrics, therefore we need to be able to handle generated tokens manually.
@mikejw, can you provide some examples of your implementation of Amplify.configure() and the token provider possibly? I think we may need some sample code to make sure we're not missing something. It would also be helpful if we could see the structure of the token payload.
Hi @cwomack thanks but another developer on our team got it working in the end with the following auth rule:
@auth(rules: [{ allow: owner }])
I apologise as it seems I wrongly presumed that I needed to use the oidc provider due to authenticating with Cognito outside of using the Amplify authentication components.
We're all good now.