-
Notifications
You must be signed in to change notification settings - Fork 4
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
ADR - Use NextAuth #102
base: main
Are you sure you want to change the base?
ADR - Use NextAuth #102
Changes from 4 commits
ed60ec9
13236ba
98fdcd9
bc67c3a
c6401cb
7081bc2
f1e8c73
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
# Use NextAuth over custom/provider specific solution for authentication | ||
|
||
- Status: [proposed] | ||
- Deciders: @sawyerh, @aligg, @lorenyu | ||
- Date: 2023-07-20 | ||
- Technical Story: As a user, I want to be able to easily integrate authentication into my react application with common identity providers, such as login.gov | ||
|
||
## Context and Problem Statement | ||
|
||
A common requirement for government projects is working with an identity provider (Such as login.gov or AWS Cognito). It isn't uncommon for authentication providers to be changed during the lifecycle of a project. We want to ease the concern of being "locked in" to one provider. [NextAuth](https://next-auth.js.org/) fills this need by allowing us to easily swap identity providers and providing helpful functions for retrieving user data. | ||
|
||
## Decision Drivers | ||
|
||
- **Extensible** - The user of this codebase can integrate with a variety of authentication providers. | ||
- **Maintained** - The NextAuth package is well-maintained and supported. | ||
- **Ease of use** - Developers can easily integrate the suggested approach to their applications. | ||
|
||
|
||
## Considered Options | ||
|
||
- NextAuth | ||
- Provider specific solution (such as [AWS Amplify](https://aws.amazon.com/amplify/) or [Azure AD](https://azure.microsoft.com/en-us/products/active-directory)) | ||
- Custom authentication wrapper | ||
- Leave the responsibility to each project team | ||
|
||
## Decision Outcome | ||
|
||
In-progress | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ℹ️ Will update based on feedback and decisions. |
||
|
||
## Pros and Cons of the Options | ||
|
||
### NextAuth | ||
|
||
**Pros** | ||
|
||
1. [Well supported](https://github.com/nextauthjs/next-auth) | ||
2. Extensible. NextAuth supports a variety of built-in [Providers](https://next-auth.js.org/providers/), support for [custom Providers](https://next-auth.js.org/configuration/providers/oauth#using-a-custom-provider), and [Adapters](https://next-auth.js.org/adapters). Using a custom provider, it is easy to extend | ||
|
||
**Cons** | ||
|
||
1. In the event of wanting to remove this package, It may be challenging to do so. | ||
|
||
|
||
### Provider specific Integration | ||
|
||
**Pros** | ||
|
||
1. Documentation is generally talored towards using the given service with the package. | ||
|
||
|
||
**Cons** | ||
|
||
1. Not all identity providers offer a package, thus requiring a custom solution. | ||
2. Generally, you are "locked-in" to that provider. In order to migrate away from the given provider, you will most likely need extensible code changes to support this lift. | ||
3. It may not always be optimized for how we develop applications using Next.js. | ||
|
||
|
||
### Custom Authentication Wrapper | ||
|
||
|
||
**Pros** | ||
|
||
1. We have full control of the underlying mechanism for interacting with authentication providers. | ||
|
||
|
||
**Cons** | ||
|
||
1. We will need to maintain this. | ||
2. May be more complicated to support more use-cases as we scale. | ||
|
||
|
||
### Leave the responsibility to each project team | ||
|
||
I believe this is the least desireable outcome as authentication is a common requirement in most applications. In the event a project does not need authentication, the project team could opt out of using whichever decision gets made from this document. | ||
|
||
|
||
|
||
## Example Implementation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I left an example in here. It's not a true implementation, in that I didn't verify it works as I don't have access to Login.gov API's. Assuming you have the proper secrets and domains in the content below, I don't see why it wouldn't work though. A potential improvement is mapping all of the login.gov attributes to typescript values to use in the return function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LMK if we should scrap it, keep it, or move it somewhere else. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. on the fence / don't feel super strongly about it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's a useful reference, but I think we should mention in here that it's pseudo-code/untested. |
||
|
||
The entirety of the Login.gov User attributes can be found here: https://developers.login.gov/attributes/. | ||
|
||
We can create a seperate type file to map those attributes | ||
|
||
**Filename**: `loginGovProvider.ts` | ||
```ts | ||
import { OAuth2Provider } from "next-auth/providers"; | ||
|
||
const LoginGovProvider = () => | ||
OAuth2Provider({ | ||
id: "login-gov", | ||
name: "Login.gov", | ||
scope: "openid email profile", // Define the required scopes | ||
clientId: "YOUR_LOGIN_GOV_CLIENT_ID", | ||
clientSecret: "YOUR_LOGIN_GOV_CLIENT_SECRET", | ||
authorizationUrl: "https://YOUR_LOGIN_GOV_DOMAIN/authorization", // Replace with the actual login.gov domain | ||
tokenUrl: "https://YOUR_LOGIN_GOV_DOMAIN/token", // Replace with the actual login.gov domain | ||
profileUrl: "https://YOUR_LOGIN_GOV_API_DOMAIN/userinfo", // Replace with the actual login.gov API domain | ||
profile: (profile) => { | ||
// Parse and transform the profile data | ||
return { | ||
id: profile.sub, | ||
firstName: profile.given_name, // aka first name | ||
lastName: profile.family_name, // aka last name | ||
email: profile.email, | ||
// and any other fields you need | ||
}; | ||
}, | ||
}); | ||
|
||
export default LoginGovProvider; | ||
``` | ||
|
||
**Filename**: `next-auth.config.js` | ||
```js | ||
import LoginGovProvider from "./loginGovProvider"; | ||
|
||
export default NextAuth({ | ||
// ... | ||
providers: [ | ||
// Other providers you may have | ||
LoginGovProvider(), | ||
], | ||
// ... | ||
}); | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure i agree with the part about
i think the goal is less about making it easy to switch auth providers, and more about eliminating the dependency of the rest of the template on any particular auth provider, so that project teams can use the Next.js application template even if they use a non-default provider by simply implementing a new adapter rather than needing to refactor the parts of the application that rely on auth functionality.