From ed60ec98086b75fa2e4f6cec6f7e17a01c36730e Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Tue, 20 Dec 2022 11:27:20 -0500 Subject: [PATCH 1/7] init document --- docs/decisions/app/0005-auth-wrapper.md | 159 ++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 docs/decisions/app/0005-auth-wrapper.md diff --git a/docs/decisions/app/0005-auth-wrapper.md b/docs/decisions/app/0005-auth-wrapper.md new file mode 100644 index 00000000..1423e594 --- /dev/null +++ b/docs/decisions/app/0005-auth-wrapper.md @@ -0,0 +1,159 @@ +# Authentication wrapper + +- Status: [proposed] +- Deciders: Ali, Sawyer +- Date: 2022-12-16 +- 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 authentication providers. As a result, having a built-in wrapper will help avoid repeated work across projects long-term. + +## Decision Drivers + +- Framework agnostic +- Non-blocking: The user of this repository can decide whether they want to use authentication or not: + - login.gov + - openID + - opt-out + +## Considered Options + +- Generic authentication wrapper +- Document authentication strategies and let the project team decide on their approach +- Leave the responsibility to each project team + +## Decision Outcome + +In-progress + +_Positive Consequences_ + +- Can be used signify which pages should be authenticated +- Connects to module built in this work that integrates with the providers listed above +- Provides a template for managing user authentication state + +_Negative Consequences_ + +- If there are no authentication requirements, this work will not apply to such projects. + +## Pros and Cons of the Options + +_Create a Authentication wrapper_ + +We can create a generic authentication wrapper that: + +1. Is framework agnostic, meaning that any react application can utilize this wrapper +2. Bootstraps future projects by providing a built-in authentication layer into the application + +The approach that I would suggest is using [React Context](https://reactjs.org/docs/context.html) which: + +1. Can be used by **any** react project +2. **Abstracts complex logic** - It’ll produce less clutter in individual components as the individual component doesn't need to worry about the underlying authentication provider or methods (e.g: calling `login()`) + +_Example_ + +We can create an auth context to manage common authentication usages such as: + +- Getting the user data +- Logging the user in / out +- Managing loading state + +`authContext.js`: + +```js +const AuthContext = createContext({}); + +export const AuthProvider = ({ children }) => { + const [user, setUser] = useState(null); + const [loading, setLoading] = useState(true); + const routesToNotProtect = [ + /* Routes defined here or in another file */ + ]; + + useEffect(() => { + // get user data from cookie or call to api + }, []); + + const login = async (email, password) => { + // Logs user in and sets cookie + }; + + const logout = (email, password) => { + // Removes cookie and resets user state + }; + + // protect routes - this can also be a HOC that wraps protected routes or vice-versa + if ( + isLoading || + (!isAuthenticated && window.location.pathname !== routesToNotProtect) + ) { + // redirect to login page, other defined page, or display component + } + + return ( + + {children} + + ); +}; + +export const useAuth = () => useContext(AuthContext); +``` + +For a `Nextjs` application, the authentication wrapper can be provided to the entire application as such: + +```js +_app.js; +function App({ Component, pageProps }) { + return ( + + + + ); +} +``` + +To summarize, the purpose of the authentication wrapper would be: + +1. Provide an API that **abstracts** common authentication methods such as logging in/out. +2. **Manage** the authentication state, e.g: username, email, etc.. that gets returned from the identity provider and loading state. +3. **Protect** defined routes + +With the above recommendation, I would also like to document how we can implement two different identity provider API's, [login.gov](https://login.gov/) and [openID](https://openid.net/connect/). + +#### Login.gov + +#### openID + +_Document common authentication strategies_ + +Instead of providing a built-in solution to this project, we can **document** authentication strategies either in this repository or in a confluence document. + +Some benefits of this approach are: + +- Provides documented strategies and approaches to authentication on the frontend which **existing** and **new teams** can leverage. +- + +_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. + +## Links + +- [A good article on react context with higher-order components](https://dev.to/lennythedev/prop-drilling-react-context-and-higher-order-component-hoc-40m9) +- Login.gov + - [Login.gov documentation](https://developers.login.gov/) + - [User attributes](https://developers.login.gov/attributes/) +- openId + - [FAQ](https://openid.net/connect/faq/) + - [Connect protocol overview](https://openid.net/specs/openid-connect-core-1_0.html#Overview) + +Questions: + +1. Does login.gov use openID connect? I was looking [here](https://developers.login.gov/overview/#integration-flow) and see OIDC and SAML being mentioned. +2. Is SAML still used / been used on any projects? +3. Is there a way to get access to their sandbox to test? +4. Any documentation that we have internally that may be useful? From 13236ba11e52b829383b37cc4562518fc8c361f0 Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Tue, 20 Dec 2022 11:30:13 -0500 Subject: [PATCH 2/7] remove questions --- docs/decisions/app/0005-auth-wrapper.md | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docs/decisions/app/0005-auth-wrapper.md b/docs/decisions/app/0005-auth-wrapper.md index 1423e594..16f270d0 100644 --- a/docs/decisions/app/0005-auth-wrapper.md +++ b/docs/decisions/app/0005-auth-wrapper.md @@ -150,10 +150,3 @@ I believe this is the least desireable outcome as authentication is a common req - openId - [FAQ](https://openid.net/connect/faq/) - [Connect protocol overview](https://openid.net/specs/openid-connect-core-1_0.html#Overview) - -Questions: - -1. Does login.gov use openID connect? I was looking [here](https://developers.login.gov/overview/#integration-flow) and see OIDC and SAML being mentioned. -2. Is SAML still used / been used on any projects? -3. Is there a way to get access to their sandbox to test? -4. Any documentation that we have internally that may be useful? From 98fdcd96cfeb45d84c835eb14f935323bf28c983 Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Thu, 20 Jul 2023 16:30:45 -0400 Subject: [PATCH 3/7] update adr --- docs/decisions/app/0005-auth-wrapper.md | 152 ----------------------- docs/decisions/app/0005-use-next-auth.md | 73 +++++++++++ 2 files changed, 73 insertions(+), 152 deletions(-) delete mode 100644 docs/decisions/app/0005-auth-wrapper.md create mode 100644 docs/decisions/app/0005-use-next-auth.md diff --git a/docs/decisions/app/0005-auth-wrapper.md b/docs/decisions/app/0005-auth-wrapper.md deleted file mode 100644 index 16f270d0..00000000 --- a/docs/decisions/app/0005-auth-wrapper.md +++ /dev/null @@ -1,152 +0,0 @@ -# Authentication wrapper - -- Status: [proposed] -- Deciders: Ali, Sawyer -- Date: 2022-12-16 -- 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 authentication providers. As a result, having a built-in wrapper will help avoid repeated work across projects long-term. - -## Decision Drivers - -- Framework agnostic -- Non-blocking: The user of this repository can decide whether they want to use authentication or not: - - login.gov - - openID - - opt-out - -## Considered Options - -- Generic authentication wrapper -- Document authentication strategies and let the project team decide on their approach -- Leave the responsibility to each project team - -## Decision Outcome - -In-progress - -_Positive Consequences_ - -- Can be used signify which pages should be authenticated -- Connects to module built in this work that integrates with the providers listed above -- Provides a template for managing user authentication state - -_Negative Consequences_ - -- If there are no authentication requirements, this work will not apply to such projects. - -## Pros and Cons of the Options - -_Create a Authentication wrapper_ - -We can create a generic authentication wrapper that: - -1. Is framework agnostic, meaning that any react application can utilize this wrapper -2. Bootstraps future projects by providing a built-in authentication layer into the application - -The approach that I would suggest is using [React Context](https://reactjs.org/docs/context.html) which: - -1. Can be used by **any** react project -2. **Abstracts complex logic** - It’ll produce less clutter in individual components as the individual component doesn't need to worry about the underlying authentication provider or methods (e.g: calling `login()`) - -_Example_ - -We can create an auth context to manage common authentication usages such as: - -- Getting the user data -- Logging the user in / out -- Managing loading state - -`authContext.js`: - -```js -const AuthContext = createContext({}); - -export const AuthProvider = ({ children }) => { - const [user, setUser] = useState(null); - const [loading, setLoading] = useState(true); - const routesToNotProtect = [ - /* Routes defined here or in another file */ - ]; - - useEffect(() => { - // get user data from cookie or call to api - }, []); - - const login = async (email, password) => { - // Logs user in and sets cookie - }; - - const logout = (email, password) => { - // Removes cookie and resets user state - }; - - // protect routes - this can also be a HOC that wraps protected routes or vice-versa - if ( - isLoading || - (!isAuthenticated && window.location.pathname !== routesToNotProtect) - ) { - // redirect to login page, other defined page, or display component - } - - return ( - - {children} - - ); -}; - -export const useAuth = () => useContext(AuthContext); -``` - -For a `Nextjs` application, the authentication wrapper can be provided to the entire application as such: - -```js -_app.js; -function App({ Component, pageProps }) { - return ( - - - - ); -} -``` - -To summarize, the purpose of the authentication wrapper would be: - -1. Provide an API that **abstracts** common authentication methods such as logging in/out. -2. **Manage** the authentication state, e.g: username, email, etc.. that gets returned from the identity provider and loading state. -3. **Protect** defined routes - -With the above recommendation, I would also like to document how we can implement two different identity provider API's, [login.gov](https://login.gov/) and [openID](https://openid.net/connect/). - -#### Login.gov - -#### openID - -_Document common authentication strategies_ - -Instead of providing a built-in solution to this project, we can **document** authentication strategies either in this repository or in a confluence document. - -Some benefits of this approach are: - -- Provides documented strategies and approaches to authentication on the frontend which **existing** and **new teams** can leverage. -- - -_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. - -## Links - -- [A good article on react context with higher-order components](https://dev.to/lennythedev/prop-drilling-react-context-and-higher-order-component-hoc-40m9) -- Login.gov - - [Login.gov documentation](https://developers.login.gov/) - - [User attributes](https://developers.login.gov/attributes/) -- openId - - [FAQ](https://openid.net/connect/faq/) - - [Connect protocol overview](https://openid.net/specs/openid-connect-core-1_0.html#Overview) diff --git a/docs/decisions/app/0005-use-next-auth.md b/docs/decisions/app/0005-use-next-auth.md new file mode 100644 index 00000000..095ba631 --- /dev/null +++ b/docs/decisions/app/0005-use-next-auth.md @@ -0,0 +1,73 @@ +# 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. + +## 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 + +## 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). + +**Cons** + +1. + +### 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. From bc67c3a29305a5cca1b7ea07934067833710701a Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Tue, 1 Aug 2023 14:57:32 -0400 Subject: [PATCH 4/7] update template --- docs/decisions/app/0005-use-next-auth.md | 59 ++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/docs/decisions/app/0005-use-next-auth.md b/docs/decisions/app/0005-use-next-auth.md index 095ba631..0992eb1f 100644 --- a/docs/decisions/app/0005-use-next-auth.md +++ b/docs/decisions/app/0005-use-next-auth.md @@ -7,7 +7,7 @@ ## 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. +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 @@ -34,11 +34,12 @@ In-progress **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). +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. +1. In the event of wanting to remove this package, It may be challenging to do so. + ### Provider specific Integration @@ -71,3 +72,55 @@ In-progress ### 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 + +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(), + ], + // ... +}); +``` + From c6401cb96258af57239bae8fd58ac372019f74b8 Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Tue, 1 Aug 2023 15:09:15 -0400 Subject: [PATCH 5/7] tidy up language --- docs/decisions/app/0005-use-next-auth.md | 58 ++++++++++++------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/decisions/app/0005-use-next-auth.md b/docs/decisions/app/0005-use-next-auth.md index 0992eb1f..83e0cbdb 100644 --- a/docs/decisions/app/0005-use-next-auth.md +++ b/docs/decisions/app/0005-use-next-auth.md @@ -31,49 +31,49 @@ In-progress ### NextAuth -**Pros** +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 +1. **Well supported and maintained**: NextAuth is actively developed and has a strong community behind it, providing ongoing support and updates. +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 +3. Seamless integration with Next.js: NextAuth is designed to work seamlessly with Next.js applications. It provides a simple way to handle authentication in server-rendered and client-side rendered pages, ensuring a smooth user experience. -**Cons** - -1. In the event of wanting to remove this package, It may be challenging to do so. +Cons: +1. Dependency on Next.js: NextAuth is tightly coupled with Next.js framework. If you are not using Next.js, integrating NextAuth into your existing stack may require additional effort. +2. Learning curve for customization: While NextAuth offers a high level of customization, extending it beyond the built-in functionalities may require a deeper understanding of the library and its underlying concepts. +3. Possible migration challenges: If you decide to switch away from NextAuth in the future, migrating to a different authentication solution may introduce complexities, especially if your application relies heavily on NextAuth-specific features. ### 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. +Pros: +1. Dedicated documentation and support. +2. Tailored features and optimizations. +3. Seamless integration with provider services. +4. Vendor-specific features and benefits. + +Cons: +1. Vendor lock-in. +2. Limited provider options. +3. Inflexibility with future migration. +4. Compatibility with your tech stack. +5. Learning curve for multiple providers. -### 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. +Pros: +1. Flexibility for individual project needs. +2. Customization and autonomy. +3. Reduced dependencies and overhead. +Cons: +1. Inconsistent security practices. +2. Lack of knowledge sharing and collaboration. +3. Increased development effort and duplication. +4. Complexity in managing multiple authentication solutions. ## Example Implementation From 7081bc2f57ec05688002843d23a8e1d4eb05d3a2 Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Tue, 1 Aug 2023 15:11:29 -0400 Subject: [PATCH 6/7] update language --- docs/decisions/app/0005-use-next-auth.md | 32 ++++++++++++------------ 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/decisions/app/0005-use-next-auth.md b/docs/decisions/app/0005-use-next-auth.md index 83e0cbdb..b88f554b 100644 --- a/docs/decisions/app/0005-use-next-auth.md +++ b/docs/decisions/app/0005-use-next-auth.md @@ -46,17 +46,17 @@ Cons: ### Provider specific Integration Pros: -1. Dedicated documentation and support. -2. Tailored features and optimizations. -3. Seamless integration with provider services. -4. Vendor-specific features and benefits. +1. Dedicated documentation and support. +2. Tailored features and optimizations. +3. Seamless integration with provider services. +4. Vendor-specific features and benefits. Cons: -1. Vendor lock-in. -2. Limited provider options. -3. Inflexibility with future migration. -4. Compatibility with your tech stack. -5. Learning curve for multiple providers. +1. Vendor lock-in. +2. Limited provider options. +3. Inflexibility with future migration. +4. Compatibility with your tech stack. +5. Learning curve for multiple providers. @@ -65,15 +65,15 @@ Cons: 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. Pros: -1. Flexibility for individual project needs. -2. Customization and autonomy. -3. Reduced dependencies and overhead. +1. Flexibility for individual project needs. +2. Customization and autonomy. +3. Reduced dependencies and overhead. Cons: -1. Inconsistent security practices. -2. Lack of knowledge sharing and collaboration. -3. Increased development effort and duplication. -4. Complexity in managing multiple authentication solutions. +1. Inconsistent security practices. +2. Lack of knowledge sharing and collaboration. +3. Increased development effort and duplication. +4. Complexity in managing multiple authentication solutions. ## Example Implementation From f1e8c732f8753c191bf497ca913a93bdd049dfb1 Mon Sep 17 00:00:00 2001 From: brandon-lent Date: Tue, 1 Aug 2023 15:12:05 -0400 Subject: [PATCH 7/7] bit more tidying --- docs/decisions/app/0005-use-next-auth.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/decisions/app/0005-use-next-auth.md b/docs/decisions/app/0005-use-next-auth.md index b88f554b..4bb8d3e2 100644 --- a/docs/decisions/app/0005-use-next-auth.md +++ b/docs/decisions/app/0005-use-next-auth.md @@ -42,7 +42,6 @@ Cons: 2. Learning curve for customization: While NextAuth offers a high level of customization, extending it beyond the built-in functionalities may require a deeper understanding of the library and its underlying concepts. 3. Possible migration challenges: If you decide to switch away from NextAuth in the future, migrating to a different authentication solution may introduce complexities, especially if your application relies heavily on NextAuth-specific features. - ### Provider specific Integration Pros: @@ -58,8 +57,6 @@ Cons: 4. Compatibility with your tech stack. 5. Learning curve for multiple providers. - - ### 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.