140 cognito#168
Conversation
…added required env keys to example.env, configured amplify in separate auth file only if both environment variables exist/are set.
…igure runs correctly with cognito values as strings.
…array of strings or a single string.
…e (COGNITO_USER_POOL_ID is set), but missing env variables for client_id and cognito_region both should not allow requests to go through
…into 140-Cognito
…into 140-Cognito Note: added necessary packages for aws-amplify. Did not push merged changes that existed inside .nx
…into 140-Cognito
dburkhart07
left a comment
There was a problem hiding this comment.
Amazing! Very educational for me to read through as well!
…or greater accessiblity
… of never type for mock requests
… any env variables)
…autogenerated in vite.config, also set the project root to allow frontend access to root /.env file.
…into 140-Cognito
CognitoJWTPayload to just AccessTokenPayload for accuracy, javadoc comments
…into 140-Cognito
| typeof payload.iss === 'string' && | ||
| typeof payload.token_use === 'string' && | ||
| typeof payload.exp === 'number' && | ||
| typeof payload.iat === 'number' |
There was a problem hiding this comment.
should check that this is in the past
There was a problem hiding this comment.
hmm, not sure what you mean by the past? jwt.verify will check for expired tokens though and return err on the guard.
There was a problem hiding this comment.
bump: Not sure what this meant mb
logging for debugging Cognito errors, added exception message for missing bearer token
dburkhart07
left a comment
There was a problem hiding this comment.
hopefully some last comments. c4c security is becoming so good!!!!!!
| } | ||
|
|
||
| // Check if the cognito information is present in the environment variables | ||
| export const cognitoInformationPresent = |
There was a problem hiding this comment.
can we just make this a function just like the backend, and call that the same way?
There was a problem hiding this comment.
For the backend I changed it to check if cognito config returns a real config or null which is contingent on having those variables present. I think they're already the same? I can just mirror both config setups to empty (frontend) or null (backend) if the variables are missing or empty.
There was a problem hiding this comment.
They now mirror eachother (Just see if they are null or empty values)
| } | ||
|
|
||
| // Checks if the value is a non-empty string | ||
| function isNonEmptyEnv(value: string | undefined): value is string { |
There was a problem hiding this comment.
we should make this function the exact same thing as the frontend as well, so we can reject null entries and dont have to worry at all about the frontend and backend disagreeing about whether auth is enabled or not.
There was a problem hiding this comment.
The functions (isAuthEnabled and isNonEmptyEnv) for checking if auth is enabled or not is the exact same, but I can maybe move that functionality to the /shared folder so we know 100% it is identical??
| import { APP_GUARD } from '@nestjs/core'; | ||
| import { CognitoService } from './cognito.service'; | ||
|
|
||
| @Global() |
There was a problem hiding this comment.
i think, for modules that rely on env variables to function entirely (so all of our aws modules), we should be validating the env variables at compile time. can we change this to rather use something like this:
export class CognitoModule implements OnModuleInit {
private readonly logger = new Logger(CognitoModule.name);
onModuleInit() {
const config = isAuthEnabled();
if (config === null) {
this.logger.warn('Cognito auth disabled: no env vars set. All routes open.');
} else {
this.logger.log(`Cognito auth enabled for pool ${config.userPoolId}`);
}
}
}
while you are at it, would you mind making this change for the s3 and ses, where we would check the specific env variables that we need to check for ses being enabled, and s3 being enabled?
There was a problem hiding this comment.
Ill put the s3 ses changes into a separate PR
shared util folder - maybe rename file
cognito configuration returns a valid configuration (returns null if missing), VITE_ warning in example.env
frontend with Amplify, cognito module now logs error for Cognito auth disabled on launch. Don't export guard.
dburkhart07
left a comment
There was a problem hiding this comment.
all nits are small, so im going to improve. make sure after all these changes the README is fully up to date. thanks for doing so much work on this, was by far the hardest module to implement!
| const clientId = process.env.COGNITO_CLIENT_ID; | ||
|
|
||
| if ( | ||
| !( |
There was a problem hiding this comment.
i think, if any of these 3 are not set, we should return null. when we go to getCognitoConfig, if its null we should instead say one of the env vars are not set, so cognito is not enabled
There was a problem hiding this comment.
Rn it is already checking to see that if not all 3 are set, then getcognitoconfig() returns null. IsAuthEnabled() is a function used by both the guard and the module (OnInit) and log warnings in the console saying that the env vars are not set. That being said i agree the logic is a bit confusing. Will go ahead and take out the unneccessary demorgans law.
|
|
||
| onModuleInit() { | ||
| if (!isAuthEnabled()) { | ||
| this.logger.warn( |
There was a problem hiding this comment.
now that i think about this, we should log an error when in production. for dev, a warning is fine. can we put somewhere in the readme that, for production, these should be changed to throw warnings instead, should they be used?
There was a problem hiding this comment.
Yes, will add to readme! I actually agree with what we talked about previously on how we may not want to disable auth entirely by default if just one cognito env value is missing, and instead loudly fail the backend on startup? - unless I misread our convo
| return null; | ||
| } | ||
|
|
||
| return { |
There was a problem hiding this comment.
i know i said the opposite before, but i think we can remove the region from the checking altogether. the region is only used here, and it can be derived from the userPoolId (const region = userPoolId.split('_')[0];)
we should do this instead and remove the env variable checks altogether. this will make it much easier to avoid any potential configuration issues
There was a problem hiding this comment.
Quick clarification: You mean remove the env variable checks for just region correct?
|
this is a question for when @maxn990 reviews this. with this flow, do we still need the auth directory, or anything from within it? i know ssf used little to nothing from it, so i wonder if part of the pr should be to delete this. it is scaffolding though, so if we want the option im not against keeping it. |
duplicate warning logged. Comments on switching to warning in prod
I'm good with deleting it if we're not using it |
Since we use amplify Authenticator to handle login/logout/signup a lot of the functionality built into the auth directory is no longer needed. New cognito module just verifies an cognito-issued access token to authorize access. We will need to edit the users folder though @dburkhart07 @maxn990 I can put that also in another pr after this is merged with the deleted /auth/ directory? edit: won't allow me to commit with those missing deleted dependencies so just going to edit them now. |
ℹ️ Issue
Closes #140
📝 Description
Created an easily-importable NestJS guard that can be used by future projects to implement Cognito Authentication into their application. Amplify on the frontend authenticates users, providing registered users with a JWT access token that can be used to access authorized routes.
Briefly list the changes made to the code:
✔️ Verification
Backend TESTS:


Frontend TESTS:


No Auth:
With Auth:
🏕️ (Optional) Future Work / Notes
@aws-amplify/ui-react/styles.csslibrary on main.tsx to use their premade styling?NEW: I think that a workshop on Authentication / Authorization would be helpful for future devs, would 100% be up to helping with that! I spent wayyy too much time figuring out the difference between the two and their uses in larger apps like which scaffolding will fork off of.