keystonejs / keystonejs/keystone
Access operation function called with no session during successful login
- Dominant language
- TypeScript
- Stars
- 10k
- Forks
- 1.3k
- Avg merge
- 19h 14m
- Merged PRs (30d)
- 19
Description
Hi,
The access operation function is been called with undefined session during a successful login. Here the steps to get where I am:
### 1.
Create and empty project with:
```
npm create keystone-app@latest
```
This creates a new project with:
```
"dependencies": {
"@keystone-6/auth": "^8.0.0",
"@keystone-6/core": "^6.0.0",
"@keystone-6/fields-document": "^9.0.0",
"typescript": "^5.5.0"
}
```
### 2.
Introduce the `isAdmin` checkbox, like shown in “Authentication and Access Control” guide. That means in `schema.ts` to add `isAdmin` field to the `User` list:
```
isAdmin: checkbox(),
```
and in `auth.ts` set
```
sessionData: 'id name isAdmin',
```
and
```
itemData: {isAdmin: true}
```
### 3.
Introduce the `Company` list defined as follows:
```
Company: list({
access: {
operation({ operation, session }){
const data = session?.data;
const userId = data?.id;
const isAdmin = data?.isAdmin;
return typeof userId == "string" && (isAdmin || operation == 'query');
}
},
fields: {
name: text(),
allowFeatureA: checkbox(),
allowFeatureB: checkbox(),
users: relationship({ ref: 'User.company', many: true }),
}
}),
```
This references a new relationship in `User` too:
```
company: relationship({ ref: 'Company.users', many: false }),
```
### 4.
That’s all. Now access the Admin UI and create a first admin user. Create a company for your user. Then logout and execute the following login:
```
mutation loginMutation($email: String!, $password: String!) {
authenticateUserWithPassword(email: $email, password: $password) {
... on UserAuthenticationWithPasswordSuccess {
item {
id
name
email
company {
id
name
allowFeatureA
allowFeatureB
}
}
}
}
}
```
providing the good `email` and `password`.
### Expected behavior
- the `Company` list access operation is called with a `session` with loaded data.
- the result of the mutation depends on final authentication state, not on previous authentication state.
### Occurring behavior
- the `Company` list access operation is called with an `undefined` `session`.
- the result of the mutation depends on previous authentication state, not on final authentication state.
### Notes
- the `Company` list access operation is called with `operation=="query"`, which it is fine since it is not related to the running mutation but it is related to walking a relationship.
- When I'm already logged in and I'm performing an useless login, it returns my company in `item`.
### Questions
- Is this the expected behavior from Keystone?
- How can I get session data as result of a successful login mutation?
Thanks a lot!
Contributor guide
Research direction
Reproduce the issue from the steps using the generated schema.ts and auth.ts, then run the supplied login mutation after logging out. Trace the authentication flow and the Company relationship query to compare the session used during login with the final authenticated session. Done means the access operation receives the final session data and the mutation result does not depend on the previous authentication state.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- graphql, node.js, typescript
- Domain
- api, authentication, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100