-
Notifications
You must be signed in to change notification settings - Fork 995
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Bug?]: Context is empty #11576
Comments
@razzeee Thanks for reporting! This looks so strange. I'm tagging @Josh-Walker-GM and @Tobbe to see if they have any ideas or have seen anything similar? |
Nothing that comes to mind right now I'm afraid |
Any more details? That code snippet is within dbAuth itself, which you normally don’t have access to within an app. Where are you accessing |
I figured out how to get it to work again, but I'm not 100% sure, which part the actual fix was We have had a docker setup since before it was available with redwood
If I pin it like this, it starts working again:
The prisma pin might actually not be needed, it started to work, after pinning the cli (we can probably pin something newer) |
@razzeee, can you provide a small repo with a reproduction of this issue? And I echo @cannikin's question — where are you attempting to access context? The only time I've seen context be unexpectedly empty is when experiencing cookie issues, though without more information it's tough to know what the issue could be. |
I'm not sure, that there is much to repro. It seems like installing Our problem is just, that we need it in the pipeline right now and can't sync the version from |
Jumping in a bit late here, but are you in v8 importing ... import context from redwood/packages/context/src/context.ts Line 23 in bef7939
|
I don't think we're doing anything special there |
Sorry, does that mean you are importing it with the context package or just relying on the global context from the global plugin. sharing some code would help us understand how it’s used and might help us think of why it’s not behaving as you expect. |
I'm not sure, how that code will help with this. As said, just using the correct version in our deploy build fixed it. Here's our full import https from 'https'
import axios from 'axios'
import { Role } from 'types/role'
import { AuthContextPayload } from '@redwoodjs/api'
import { AuthenticationError, ForbiddenError } from '@redwoodjs/graphql-server'
import {
updateUserWithoutLogin,
userByGitlabhandle,
} from 'src/services/users/users'
import Sentry from './sentry'
// As we only have a self signed cert, we need this
const axiosInstance = axios.create({
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
})
/**
* getCurrentUser returns the user information together with
* an optional collection of roles used by requireAuth() to check
* if the user is authenticated or has role-based access
*
* !! BEWARE !! Anything returned from this function will be available to the
* client--it becomes the content of `currentUser` on the web side (as well as
* `context.currentUser` on the api side). You should carefully add additional
* fields to the return object only once you've decided they are safe to be seen
* if someone were to open the Web Inspector in their browser.
*
* @see https://github.com/redwoodjs/redwood/tree/main/packages/auth for examples
*
* @param _decoded - The decoded access token containing user info and JWT
* claims like `sub`. Note, this could be null.
* @param { token, SupportedAuthTypes type } - The access token itself as well
* as the auth provider type
* @param { APIGatewayEvent event, Context context } - An optional object which
* contains information from the invoker such as headers and cookies, and the
* context information about the invocation such as IP Address
* @returns RedwoodUser
*/
export const getCurrentUser = async (
_decoded: AuthContextPayload[0],
{ token }: AuthContextPayload[1],
_invoker: AuthContextPayload[2]
) => {
if (!token) {
throw new Error('No token provided')
}
// ask gitlab for user data
const user = await axiosInstance.get(
`${process.env.GITLAB_AUTHORITY}/api/v4/user`,
{
headers: {
Authorization: `Bearer ${token}`,
},
}
)
if (user.status !== 200) {
throw new Error('User not found in gitlab or gitlab unavailable')
}
if (user.data.external === true) {
throw new ForbiddenError('External users are not allowed to login')
}
const userExists = await userByGitlabhandle({
gitlabhandle: user.data.username,
})
Sentry.setUser({ username: user.data.username, id: user.data.id })
if (userExists) {
if (user.data.id !== userExists.gitlabId) {
await updateUserWithoutLogin({
gitlabhandle: userExists.gitlabhandle,
input: {
gitlabId: user.data.id,
},
})
}
await updateUserWithoutLogin({
gitlabhandle: userExists.gitlabhandle,
input: {
lastSeen: new Date(),
},
})
return {
...userExists,
roles: userExists.userRole.map((r) => r.role.name),
gitlabId: user.data.id,
gitlabhandle: user.data.username,
internalAvatar: userExists.userImage.find(
(a) => a.imageType === 'INTERNAL_AVATAR' && a.deletedAt === null
)?.imageBase64,
}
} else {
throw new Error(`User not found: ${user.data.username}`)
}
}
/**
* The user is authenticated if there is a currentUser in the context
*
* @returns {boolean} - If the currentUser is authenticated
*/
export const isAuthenticated = (): boolean => {
return !!context.currentUser
}
/**
* When checking role membership, roles can be a single value, a list, or none.
* You can use Prisma enums too (if you're using them for roles), just import your enum type from `@prisma/client`
*/
type AllowedRoles = Role | Role[] | undefined
/**
* Checks if the currentUser is authenticated (and assigned one of the given roles)
*
* @param roles: {@link AllowedRoles} - Checks if the currentUser is assigned one of these roles
*
* @returns {boolean} - Returns true if the currentUser is logged in and assigned one of the given roles,
* or when no roles are provided to check against. Otherwise returns false.
*/
export const hasRole = (roles: AllowedRoles): boolean => {
if (!isAuthenticated()) {
return false
}
const currentUserRoles = context.currentUser?.roles as Role[]
if (typeof roles === 'string') {
if (typeof currentUserRoles === 'string') {
// roles to check is a string, currentUser.roles is a string
return currentUserRoles === roles
} else if (Array.isArray(currentUserRoles)) {
// roles to check is a string, currentUser.roles is an array
return currentUserRoles?.some((allowedRole) => roles === allowedRole)
}
}
if (Array.isArray(roles)) {
if (Array.isArray(currentUserRoles)) {
// roles to check is an array, currentUser.roles is an array
return currentUserRoles?.some((allowedRole) =>
roles.includes(allowedRole)
)
} else if (typeof currentUserRoles === 'string') {
// roles to check is an array, currentUser.roles is a string
return roles.some((allowedRole) => currentUserRoles === allowedRole)
}
}
// roles not found
return false
}
/**
* Use requireAuth in your services to check that a user is logged in,
* whether or not they are assigned a role, and optionally raise an
* error if they're not.
*
* @param roles?: {@link AllowedRoles} - When checking role membership, these roles grant access.
*
* @returns - If the currentUser is authenticated (and assigned one of the given roles)
*
* @throws {@link AuthenticationError} - If the currentUser is not authenticated
* @throws {@link ForbiddenError} - If the currentUser is not allowed due to role permissions
*
* @see https://github.com/redwoodjs/redwood/tree/main/packages/auth for examples
*/
export const requireAuth = ({ roles }: { roles?: AllowedRoles } = {}) => {
if (!isAuthenticated()) {
throw new AuthenticationError("You don't have permission to do that.")
}
if (roles && !hasRole(roles)) {
throw new ForbiddenError("You don't have access to do that.")
}
} |
Then can I close out the issue? Do we need to fix some docs or release notes? Just trying to figure out next steps - the team rotates weekly on issue triage and want to make sure have enough info to pass on to get to a resolution. |
I think we can close this. We need to migrate to redwoods docker deploy at some point (does it do database and data migrations on startup?) and then it should hopefully not happen anymore, as it's handled by that? |
What's not working?
Context is
{}
when using it similar toredwood/packages/auth-providers/dbAuth/setup/src/templates/api/lib/auth.ts.template
Line 49 in 2b74931
The interesting this is, that we're still on redwood 7 and it seemed to break for no reason. I was guessing a dependency update, but wasn't able to pinpoint it so far.
It also seems to be fine in dev, but breaks for us with docker/deploy (our own docker stuff, pre redwood docker)
How do we reproduce the bug?
I'm lost on this so far, mostly want to reach out and see, if anything comes to mind. Might task a colleague to condense a repro repo, if nothing else happens.
What's your environment? (If it applies)
Are you interested in working on this?
The text was updated successfully, but these errors were encountered: