Open malcomm opened 2 years ago
@malcomm - can you give more specifics with how you set up your auth and user groups? Also, how are you making your mutations/create requests? This feature works as expected, so I think you are setting up auth and/or creating records with the incorrect access. Thank you.
@danielleadams - note: this project was previously a transformer v1 implementation.
My setup:
admin
admin
groupthis.apiService.ListFoo();
@danielleadams - I even deleted my environment and started over from a brand new environment. Still not working. I've tried multiple models to query and no matter what I do the groups
auth is not work.
@malcomm What client library are using and is this a mocked or deployed server?
@danielleadams - I'm using Angular on the frontend and calling the generated APIService
for the graphql/DynamoDB backend. I have deployed servers that I'm hitting via the standard amplify push
. Here's my amplify status
:
> amplify status
Current Environment: devthree
┌───────────┬─────────────────────────┬───────────┬───────────────────┐
│ Category │ Resource name │ Operation │ Provider plugin │
├───────────┼─────────────────────────┼───────────┼───────────────────┤
│ Auth │ foof6ac14a6. │ No Change │ awscloudformation │
├───────────┼─────────────────────────┼───────────┼───────────────────┤
│ Api │ fooapi │ No Change │ awscloudformation │
├───────────┼─────────────────────────┼───────────┼───────────────────┤
│ Analytics │ fooui │ No Change │ awscloudformation │
└───────────┴─────────────────────────┴───────────┴───────────────────┘
Foo is not the name on the resources, just omitted those to keep it generic for the ticket. I'm happy to supply the specifics of my environments via other channels.
Also, here's a very simple model that I'm experiencing this error:
type IssueComment
@model
@auth(rules: [
{ allow: groups, groups: ["admin", "practitioner"] }
])
# @key(name: "byIssue", fields: ["issueID"])
{
id: ID!
issueID: ID! @index(name: "byIssue")
createdAt: AWSDateTime
updatedAt: AWSDateTime
author: String
comment: String
}
@danielleadams - also of note: it looks like the permissions are setup correctly from the API perspective:
> amplify status api -acm IssueComment
userPools:staticGroup:admin
┌───────────┬────────┬──────┬────────┬────────┐
│ (index) │ create │ read │ update │ delete │
├───────────┼────────┼──────┼────────┼────────┤
│ id │ true │ true │ true │ true │
│ issueID │ true │ true │ true │ true │
│ createdAt │ true │ true │ true │ true │
│ updatedAt │ true │ true │ true │ true │
│ author │ true │ true │ true │ true │
│ comment │ true │ true │ true │ true │
└───────────┴────────┴──────┴────────┴────────┘
userPools:staticGroup:practitioner
┌───────────┬────────┬──────┬────────┬────────┐
│ (index) │ create │ read │ update │ delete │
├───────────┼────────┼──────┼────────┼────────┤
│ id │ true │ true │ true │ true │
│ issueID │ true │ true │ true │ true │
│ createdAt │ true │ true │ true │ true │
│ updatedAt │ true │ true │ true │ true │
│ author │ true │ true │ true │ true │
│ comment │ true │ true │ true │ true │
└───────────┴────────┴──────┴────────┴────────┘
Hey @malcomm - I've been doing some testing on my end, and it appears the ACM is correct. I'm not able to reproduce your issue with the auth setup you've shared. Do you mind running the queries in AppSync to see if we can isolate the issue to either the front end or the backend?
@danielleadams - I was able to run the query from AppSync when logged into Cognito.
I'm looking through my application now to make sure everything is configured correctly.
@danielleadams - I looked at my config and setup and it's all pretty standard. The one thing I forgot to mention:
"aws-amplify": "^4.3.13",
I'm also not using the @aws-amplify/ui-angular
package. Instead, I'm handling authentication using my own authentication service. But in the end, it does the same thing:
import { Auth } from 'aws-amplify';
...
async login(username: string, password: string): Promise<CognitoUser> {
const user = await Auth.signIn(username, password);
this.currentUser = user;
return user;
}
This was all working great under Transformer v1. Unless I'm doing something just silly, this seems like there's a bug?
@malcomm I'm going to transfer this to amplify-js repo so you can chat with that team. Unfortunately, I don't have much knowledge on the library.
Hi @malcomm 👋 a couple things to check:
Amplify.configure
and share the logs from the consoleAmplify.Logger.LOG_LEVEL = 'DEBUG';
Are you certain the user you are authenticating and making the call with is assigned to one of the user groups specified in the auth rule?
Do you see a difference in behavior/responses between the client and AppSync console?
@chrisbonifacio
[DEBUG] 05:57.7 Credentials - credentials not changed and not expired, directly return
ConsoleLogger.js:127 [DEBUG] 05:57.8 AuthClass - getting current authenticated user
ConsoleLogger.js:127 [DEBUG] 05:57.8 AuthClass - get current authenticated userpool user
ConsoleLogger.js:127 [DEBUG] 05:57.8 Credentials - removing aws-amplify-federatedInfo from storage
admin
group in CognitoNot Authorized to access listIssueComments on type Query
. AppSync console is not.Can you share what the code for the query looks like as well as the network request/response? Want to check if Amplify is including an auth token in the request.
Otherwise, what are the default and additional authentication types for your AppSync API?
@chrisbonifacio - as for auth types, I'm not sure what you mean by that exactly. I can say this: we are using only Cognito and I was able to login as the same user in AppSync and issue a query. The same query via client/angular is throwing the error.
As for the code that's causing this:
console.log('comments: ', this.apiService.ListIssueComments());
Which is the generated code for graphql:
async ListIssueComments(
filter?: ModelIssueCommentFilterInput,
limit?: number,
nextToken?: string
): Promise<ListIssueCommentsQuery> {
const statement = `query ListIssueComments($filter: ModelIssueCommentFilterInput, $limit: Int, $nextToken: String) {
listIssueComments(filter: $filter, limit: $limit, nextToken: $nextToken) {
__typename
items {
__typename
id
issueID
createdAt
updatedAt
author
comment
}
nextToken
}
}`;
const gqlAPIServiceArguments: any = {};
if (filter) {
gqlAPIServiceArguments.filter = filter;
}
if (limit) {
gqlAPIServiceArguments.limit = limit;
}
if (nextToken) {
gqlAPIServiceArguments.nextToken = nextToken;
}
const response = (await API.graphql(
graphqlOperation(statement, gqlAPIServiceArguments)
)) as any;
return <ListIssueCommentsQuery>response.data.listIssueComments;
}
For your appsync authentication types, you can check either the aws-exports.js
or the backend-config.json
files generated by the CLI.
For example, this is my backend-config for my AppSync resource:
"authConfig": {
"defaultAuthentication": {
"authenticationType": "API_KEY",
"apiKeyConfig": {
"apiKeyExpirationDays": 7
}
},
"additionalAuthenticationProviders": [
{
"authenticationType": "AMAZON_COGNITO_USER_POOLS",
"userPoolConfig": {
"userPoolId": "authissue9535f0ef735e"
}
}
]
}
But, if your default auth type is Cognito User Pools, then you should not be getting an Unauthorized error.
Can you try adjusting your API.graphql
call to include an authMode
of "AMAZON_COGNITO_USER_POOLS" to make sure there is a Cognito token being set in the authorization header?
example:
const response = await API.graphql({
...graphqlOperation(statement, gqlAPIServiceArguments),
authMode: "AMAZON_COGNITO_USER_POOLS",
});
@chrisbonifacio - I could not make that change because the generated code doesn't have that as an option (at least not the way you've got it - causes compiler errors). I was trying to make it work, but didn't have time. Feels like it's not the correct way of passing authMode.
@chrisbonifacio - just to be sure, I don't have a path to move forward here.
It works in my angular app, had to change it in the API.service.ts
file. But, I think you're right, even if you got it to work, this isn't an ideal way to deal with this. The file would be overwritten every time you push and you'd have to adjust the authMode for each mutation function. The auto-generated functions don't accept an argument for you to set the authMode
so the only way around it (that I'm aware of) would be to change your codegen configuration to generate typescript files instead of graphql files (from choosing angular) and running the mutations similar to this:
// app.component.ts
import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { API } from 'aws-amplify';
import { IssueComment } from './API.service';
import { createIssueComment } from 'src/graphql/mutations';
import { listIssueComments } from 'src/graphql/queries';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent implements OnInit {
title = 'amplify-angular-app';
public createForm: FormGroup;
/* declare IssueComments variable */
public IssueComments: Array<IssueComment> = [];
constructor(private fb: FormBuilder) {
this.createForm = this.fb.group({
author: ['', Validators.required],
comment: ['', Validators.required],
issueID: ['1234', Validators.required],
});
}
async ngOnInit() {
/* fetch IssueComments when app loads */
const event = (await API.graphql({
query: listIssueComments,
authMode: 'AMAZON_COGNITO_USER_POOLS',
})) as any;
this.IssueComments = event.data.listIssueComments.items as IssueComment[];
}
public async onCreate(IssueComment: IssueComment) {
try {
await API.graphql({
query: createIssueComment,
variables: {
input: {
...IssueComment,
},
},
authMode: 'AMAZON_COGNITO_USER_POOLS',
});
console.log('item created!');
this.createForm.reset();
} catch (e) {
console.log('error creating IssueComment...', e);
}
}
}
@chrisbonifacio - right, this is not how things are supposed to work, so we are agreed. This is a bug.
I don't think it's a bug because the codegen is working as intended but it should be updated to add an argument for setting the authMode. I'm going to transfer this over to the CLI repo since this is more of a codegen issue.
Hi @malcomm, can we try one more thing to see if this solves the problem. In the aws-exports.js file, what is the value of the aws_appsync_authenticationType
field? I was able to reproduce the same 401 error, and that was caused by aws_appsync_authenticationType
being set to other auth types than AMAZON_COGNITO_USER_POOLS. Once I changed the value to AMAZON_COGNITO_USER_POOLS, it starts to work for me. Can you try and see if it works for you?
Doc reference for aws_appsync_authenticationType
: https://docs.amplify.aws/lib/graphqlapi/create-or-re-use-existing-backend/q/platform/js/#re-use-existing-appsync-graphql-api
I was facing a similar situation locally when groups
wasn't working when I was using the amplify mock
command. For what it's worth, I did this:
npm i -g @aws-amplify/cli // This performed an upgrade from 7.6.23 → 8.0.3
npm ci // deleted and re-installed my node_modules
groups
started working again with amplify mock
I also met this problem, after I added "authMode: 'AMAZON_COGNITO_USER_POOLS'", it can query successfully.
As per today I experienced this bug using latest Amplify cli v10.8.1 with React.js v18 I solved it by modifying the aws-export.js file like this post mentioned: https://github.com/aws-amplify/amplify-codegen/issues/387#issuecomment-1092177790 but every time I run amplify push api, the bug comes back
In the AppSync console settings, i tried switching the AMAZON_COGNITO_USER_POOLS as Default authorization mode and put the other method I was using as default in the Additional authorization providers sections. But that did not fix it. Still need to change aws-export.js after each push
Changing the default auth mode with the cli works!
It works in my angular app, had to change it in the
API.service.ts
file. But, I think you're right, even if you got it to work, this isn't an ideal way to deal with this. The file would be overwritten every time you push and you'd have to adjust the authMode for each mutation function. The auto-generated functions don't accept an argument for you to set theauthMode
so the only way around it (that I'm aware of) would be to change your codegen configuration to generate typescript files instead of graphql files (from choosing angular) and running the mutations similar to this:// app.component.ts import { Component, OnInit } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; import { API } from 'aws-amplify'; import { IssueComment } from './API.service'; import { createIssueComment } from 'src/graphql/mutations'; import { listIssueComments } from 'src/graphql/queries'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) export class AppComponent implements OnInit { title = 'amplify-angular-app'; public createForm: FormGroup; /* declare IssueComments variable */ public IssueComments: Array<IssueComment> = []; constructor(private fb: FormBuilder) { this.createForm = this.fb.group({ author: ['', Validators.required], comment: ['', Validators.required], issueID: ['1234', Validators.required], }); } async ngOnInit() { /* fetch IssueComments when app loads */ const event = (await API.graphql({ query: listIssueComments, authMode: 'AMAZON_COGNITO_USER_POOLS', })) as any; this.IssueComments = event.data.listIssueComments.items as IssueComment[]; } public async onCreate(IssueComment: IssueComment) { try { await API.graphql({ query: createIssueComment, variables: { input: { ...IssueComment, }, }, authMode: 'AMAZON_COGNITO_USER_POOLS', }); console.log('item created!'); this.createForm.reset(); } catch (e) { console.log('error creating IssueComment...', e); } } }
Thanks for the clarification. This is correct because aws amplify is deny first by default, so you have to call cognito pool for the authorization, then you can perform group specific CRUD stuff. It is safe though because they cannot change their cognito status because its deny first
Before opening, please confirm:
How did you install the Amplify CLI?
npm
If applicable, what version of Node.js are you using?
v16.13.2
Amplify CLI Version
7.6.12
What operating system are you using?
macos
Did you make any manual changes to the cloud resources managed by Amplify? Please describe the changes made.
no
Amplify Categories
auth, api
Amplify Commands
Not applicable
Describe the bug
Getting:
Not Authorized to access listFoo on type Query
When performing a list on the model
Expected behavior
Group authentication should work as documented
Reproduction steps
GraphQL schema(s)
Log output
Additional information
No response