Skip to content
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

[Feature request] Support multiple Cognito user pool clients #216

Open
jmorgancusick opened this issue Oct 4, 2022 · 4 comments
Open

[Feature request] Support multiple Cognito user pool clients #216

jmorgancusick opened this issue Oct 4, 2022 · 4 comments

Comments

@jmorgancusick
Copy link

We have been using this lambda@edge + cognito solution for some time to host an internal static site. We'd like to expand its use so that we can easily spin up other static sites behind cognito auth. Looking at the current implementation, it seems the only way to achieve this is to spin up multiple lambdas@edge (i.e., one parseAuth lambda for each static site). This is because the lambdas search their disk configuration.json for the cognito app id when authenticating. What we'd like is the ability to use a single parseAuth (and others) lambad@edge to handle authorization to multiple different cognito app ids.

One way to achieve this is to convert the app id key in the configuration.json to an app id map, which would map domain names to congito app id. Lambda logic could be updated to look something like this:

parseAuth -- before

export const handler: CloudFrontRequestHandler = async (event) => {
  CONFIG.logger.debug("Event:", event);
  const request = event.Records[0].cf.request;
  const domainName = request.headers["host"][0].value;
  const cognitoTokenEndpoint = `https://${CONFIG.cognitoAuthDomain}/oauth2/token`;
  let redirectedFromUri = `https://${domainName}`;
  let idTokenInCookies: string | undefined = undefined;
  try {
    const cookies = common.extractAndParseCookies(
      request.headers,
      CONFIG.clientId,
      CONFIG.cookieCompatibility
    );
...

parseAuth -- after

export const handler: CloudFrontRequestHandler = async (event) => {
  CONFIG.logger.debug("Event:", event);
  const request = event.Records[0].cf.request;
  const domainName = request.headers["host"][0].value;
  const cognitoTokenEndpoint = `https://${CONFIG.cognitoAuthDomain}/oauth2/token`;
  let redirectedFromUri = `https://${domainName}`;
  let idTokenInCookies: string | undefined = undefined;
  try {
    const cookies = common.extractAndParseCookies(
      request.headers,
      CONFIG.clientIdMap[domainName],  // <----------- CHANGE HERE
      CONFIG.cookieCompatibility
    );
...

Some other tweaks to getConfigWithJwtVerifier() would also be necessary.

If one wanted to generalize, one could really have the whole confiurationg.json be the value of a map from domainName to config.

Another thought is to be able to override cognito app ID (and potentially other cognito params) with cookies that cloudfront would presumably set. Not sure if I like this as much, given that an unauthorized user could maliciously set cognito parameters via the cookies and you're relying on a developer to make sure they properly rewrite any maliciously formed cookies in their cloudfront distribution.

Anyway, I'd be willing to do fork the repo and implement a version of this. I'd love to contribute back to this project though and am trying to get a sense if such a change would be accepted. I don't necessarily want to maintain a second copy of this whole project just for a small enhancement like this. 😅 Let me know what y'all think!

Thanks,
Jack

@ottokruse
Copy link
Collaborator

Hi Jack, thanks for the proposal!

Question, what would be the advantage over just deploying Auth@Edge for each client ID?
(You could reuse the same user pool and provide a separate client ID for each deployment)

@jmorgancusick
Copy link
Author

jmorgancusick commented Oct 6, 2022

Hey @ottokruse, no problem and thanks for your response.

Yes one could deploy Auth@Edge for each client ID, but that's six lambdas per client ID, with each set performing nearly identical duties. We'd like to use Auth@Edge to host many static sites. I could see us scaling to use 20 or 30 app client IDs. With a new deployment for each client ID, we would have nearly 200 lambda functions that need to be deployed, monitored and maintained. This does not follow the DRY principle.

Alternatively, if we modify the lambdas slightly to handle interfacing with the proper app ID given the request domain name, we could just use 6 lambdas for all of our static sites.

@ottokruse
Copy link
Collaborator

What's the background of using a ClientID per site? What's the benefit you're after? Asking since this mechanism can't be used to e.g. have difference in access rights for you User Pool's users. (You'd need e.g. groups for that)

@ottokruse
Copy link
Collaborator

What strategy did you end up pursuing @jmorgancusick ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants