diff --git a/packages/nestjs-auth-github/README.md b/packages/nestjs-auth-github/README.md index fc4d17f2..ff7ab2ed 100644 --- a/packages/nestjs-auth-github/README.md +++ b/packages/nestjs-auth-github/README.md @@ -15,13 +15,10 @@ Authenticate requests using GitHub OAuth2 1. [Tutorials](#tutorials) - [Introduction](#introduction) - [Getting Started with GitHub Authentication](#getting-started-with-github-authentication) - - [Step 1: Create User Entity](#step-1-create-user-entity) - - [Step 2: Create Federated Entity](#step-2-create-federated-entity) - - [Step 3: Implement FederatedUserLookupServiceInterface](#step-3-implement-federateduserlookupserviceinterface) - - [Step 4: Implement FederatedUserMutateServiceInterface](#step-4-implement-federatedusermutateserviceinterface) - - [Step 5: Implement IssueTokenServiceInterface](#step-5-implement-issuetokenserviceinterface) - - [Step 6: Environment Variables](#step-6-environment-variables) - - [Step 7: Configure the Module](#step-7-configure-the-module) + - [Step 1: Associate User Entity to Federated Entity](#step-1-associate-user-entity-to-federated-entity) + - [Step 2: Associate Federated Entity to User Entity](#step-2-associate-federated-entity-to-user-entity) + - [Step 3: Environment Variables](#step-3-environment-variables) + - [Step 4: Configure the Module](#step-4-configure-the-module) 2. [Testing the GitHub Authentication Flow](#testing-the-github-authentication-flow) 3. [How-To Guides](#how-to-guides) - [Customizing the Issue Token Service](#customizing-the-issue-token-service) @@ -47,7 +44,10 @@ official documentation](https://docs.github.com/en/apps/oauth-apps/building-oaut ## Getting Started with GitHub Authentication -### Step 1: Create User Entity +**Prerequisite:** Github module has a dependency on `@concepta/nestjs-federated`. Ensure you have implemented the `FederatedModule` before proceeding. Refer to +the [Federated API Documentation](https://www.rockets.tools/reference/rockets/nestjs-federated/README) for more details. + +### Step 1: Associate User Entity to Federated Entity First, let's create the `UserEntity`: @@ -68,9 +68,9 @@ export class UserEntity { } ``` -### Step 2: Create Federated Entity +### Step 2: Associate Federated Entity to User Entity -Next, create the `FederatedEntity`: +Next, associate the `UserEntity` to the `FederatedEntity`: ```ts import { Entity, ManyToOne } from 'typeorm'; @@ -84,97 +84,7 @@ export class FederatedEntity extends FederatedSqliteEntity { } ``` -### Step 3: Implement FederatedUserLookupServiceInterface - -Create a service that implements `FederatedUserLookupServiceInterface`: - -```ts -// user.mock.ts -export const mockUser = { - id: 'abc', - email: 'me@dispostable.com', - username: 'me@dispostable.com', -} -``` - -```ts -// user-lookup.service.ts -import { Injectable } from '@nestjs/common'; -import { ReferenceEmail } from '@concepta/ts-core'; -import { FederatedUserLookupServiceInterface } from '@concepta/nestjs-federated'; -import { mockUser } from './user.mock'; - - -@Injectable() -export class UserLookupServiceFixture implements FederatedUserLookupServiceInterface { - async byId(id: string): ReturnType { - if (id === mockUser.id) { - return mockUser; - } else { - throw new Error(); - } - } - - async byEmail(email: ReferenceEmail): ReturnType { - return email === mockUser.email ? mockUser : null; - } -} -``` - -### Step 4: Implement FederatedUserMutateServiceInterface - -Create a service that implements `FederatedUserMutateServiceInterface`: - -```ts -// user-mutate.service.ts -import { FederatedCredentialsInterface, FederatedUserMutateServiceInterface } from '@concepta/nestjs-federated'; -import { FederatedUserMutateInterface } from '@concepta/nestjs-federated/dist/interfaces/federated-user-mutate.interface'; -import { Injectable } from '@nestjs/common'; -import { mockUser } from './user.mock'; - -@Injectable() -export class UserMutateServiceFixture implements FederatedUserMutateServiceInterface { - async create(_object: FederatedUserMutateInterface): Promise { - return mockUser; - } -} -``` - -### Step 5: Implement IssueTokenServiceInterface - -Create a service that implements `IssueTokenServiceInterface`: - -```ts -// issue-token.service.ts -import { JwtSignOptions } from '@nestjs/jwt'; -import { AuthenticationResponseInterface } from '@concepta/ts-common'; -import { IssueTokenServiceInterface } from '@concepta/nestjs-authentication'; - -export class GitHubIssueTokenService implements IssueTokenServiceInterface { - async responsePayload(_id: string): Promise { - return { - accessToken: 'my_access_token', - refreshToken: 'my_refresh_token', - }; - } - - async accessToken( - _payload: string | object | Buffer, - _options?: JwtSignOptions | undefined, - ): Promise { - return 'my_access_token'; - } - - async refreshToken( - _payload: string | object | Buffer, - _options?: JwtSignOptions | undefined, - ): Promise { - return 'my_refresh_token'; - } -} -``` - -### Step 6: Environment Variables +### Step 3: Environment Variables `AuthGithubModule` will automatically look for predefined environment variables, to keep sensitive information secure, use environment variables for @@ -209,7 +119,7 @@ the `@nestjs/config` package: export class AppModule {} ``` -### Step 7: Configure the Module +### Step 4: Configure the Module Finally, set up the module configuration: @@ -447,7 +357,8 @@ AuthGithubModule.forRoot({ If you need to customize, how to get the user information, or how to create the user, you will need to update the federated options. Please refer for -the `nestjs-federated` documentation. +the [Federated API Documentation](https://www.rockets.tools/reference/rockets/nestjs-federated/README) +documentation. ## Reference diff --git a/packages/nestjs-federated/README.md b/packages/nestjs-federated/README.md index d7e19d99..d4c19fd3 100644 --- a/packages/nestjs-federated/README.md +++ b/packages/nestjs-federated/README.md @@ -10,6 +10,252 @@ Authenticate via federated login [![GH Contrib](https://img.shields.io/github/contributors/conceptadev/rockets?logo=github)](https://github.com/conceptadev/rockets/graphs/contributors) [![NestJS Dep](https://img.shields.io/github/package-json/dependency-version/conceptadev/rockets/@nestjs/common?label=NestJS&logo=nestjs&filename=packages%2Fnestjs-core%2Fpackage.json)](https://www.npmjs.com/package/@nestjs/common) -## Installation +# Table of Contents -`yarn add @concepta/nestjs-federated` + +1. [Tutorials](#tutorials) + - [Introduction](#introduction) + - [Getting Started with Federated Authentication](#getting-started-with-federated-authentication) + - [Step 1: Create User Entity](#step-1-create-user-entity) + - [Step 2: Create Federated Entity](#step-2-create-federated-entity) + - [Step 3: Implement FederatedUserLookupServiceInterface](#step-3-implement-federateduserlookupserviceinterface) + - [Step 4: Implement FederatedUserMutateServiceInterface](#step-4-implement-federatedusermutateserviceinterface) + - [Step 5: Configure the Module](#step-5-configure-the-module) + - [Step 6: Integrate with other Oauth Module](#step-6-integrate-with-other-oauth-module) +2. [How-To Guides](#how-to-guides) + - [Implement FederatedUserLookupServiceInterface](#implement-federateduserlookupserviceinterface) + - [Implement FederatedUserMutateServiceInterface](#implement-federatedusermutateserviceinterface) + - [Using federated with Rockets Github Module](#using-federated-with-rockets-github-module) +3. [Reference](#reference) +4. [Explanation](#explanation) + - [Federated Services](#federated-services) + - [Module Options Responsibilities](#module-options-responsibilities) + +# Tutorials + +## Introduction + +Before we begin, you'll need to set up OAuth Apps for the social providers you +wish to use (e.g., GitHub, Google, Facebook) to obtain the necessary +credentials. For detailed guides on creating OAuth Apps and obtaining your +Client IDs and Client Secrets, please refer to the official documentation of +each provider and refer to the (`@concepta/nestjs-auth-github`)[https://www.rockets.tools/reference/rockets/nestjs-auth-github/README] , (`nestjs-auth-apple`)[https://www.rockets.tools/reference/rockets/nestjs-auth-apple/README] and (`@concepta/nestjs-auth-google`)[https://www.rockets.tools/reference/rockets/nestjs-auth-google/README] documentation to use our modules. + +## Getting Started with Federated Authentication + +### Step 1: Create User Entity + +First, let's create the `UserEntity`: + +```ts +import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'; +import { FederatedEntity } from '../federated/federated.entity'; + +@Entity() +export class UserEntity { + @PrimaryGeneratedColumn('uuid') + id: string; + + @Column() + name: string; + + @OneToMany(() => FederatedEntity, (federated) => federated.user) + federated!: FederatedEntity; +} +``` + +### Step 2: Create Federated Entity + +Next, create the `FederatedEntity`: + +```ts +import { Entity, ManyToOne } from 'typeorm'; +import { FederatedSqliteEntity } from '@concepta/nestjs-federated'; +import { UserEntity } from '../user/user.entity'; + +@Entity() +export class FederatedEntity extends FederatedSqliteEntity { + @ManyToOne(() => UserEntity, (user) => user.federated) + user!: UserEntity; +} +``` + +### Step 3: Implement FederatedUserLookupServiceInterface +Refer to [Implement FederatedUserLookupServiceInterface](#implement-federateduserlookupserviceinterface) section + +### Step 4: Implement FederatedUserMutateServiceInterface +Refer to [Implement FederatedUserMutateServiceInterface](#implement-federatedusermutateserviceinterface) section + +### Step 5: Configure the Module + +Finally, set up the module configuration: + +```ts +import { AuthenticationModule, IssueTokenService } from '@concepta/nestjs-authentication'; +import { FederatedModule } from '@concepta/nestjs-federated'; +import { JwtModule } from '@concepta/nestjs-jwt'; +import { Module } from '@nestjs/common'; +import { FederatedUserLookupService } from './federated/federated-lookup.service'; +import { UserMutateServiceFixture } from './federated/federated-mutate.service'; +import { FederatedEntity } from './federated/federated.entity'; +import { AuthGithubModule } from '@concepta/nestjs-auth-github'; +import { GitHubIssueTokenService } from './github/issue-token.service'; +import { TypeOrmExtModule } from '@concepta/nestjs-typeorm-ext'; +import { UserEntity } from './user/user.entity'; + +@Module({ + imports: [ + ConfigModule.forRoot({ + isGlobal: true, + }), + TypeOrmExtModule.forRoot({ + type: 'sqlite', + database: ':memory:', + entities: [UserEntity, FederatedEntity], + }), + JwtModule.forRoot({}), + AuthenticationModule.forRoot({}), + FederatedModule.forRoot({ + entities: { + federated: { + entity: FederatedEntity, + }, + }, + userLookupService: new FederatedUserLookupService(), + userMutateService: new UserMutateServiceFixture(), + }), + ], + controllers: [], + providers: [], +}) +export class AppModule {} +``` + +This configuration uses SQLite for testing, but you can use any database +supported by TypeORM. + +### Step 6: Integrate with other Oauth Module + +To complete the integration with OAuth providers and set up the whole authentication flow, you'll need to implement one of the @concepta social authentication modules. Follow the documentation for the specific module you want to use: + +1. GitHub Authentication: + Refer to the [@concepta/nestjs-auth-github documentation](https://www.rockets.tools/reference/rockets/nestjs-auth-github/README) for detailed instructions on setting up GitHub OAuth authentication. + +2. Apple Authentication: + For Apple Sign-In, follow the [nestjs-auth-apple documentation](https://www.rockets.tools/reference/rockets/nestjs-auth-apple/README) to implement Apple's OAuth flow. + +3. Google Authentication: + To set up Google OAuth, consult the [@concepta/nestjs-auth-google documentation](https://www.rockets.tools/reference/rockets/nestjs-auth-google/README) for step-by-step guidance. + +These documentation resources will guide you through: +- Obtaining the necessary OAuth credentials from the respective providers +- Configuring the OAuth module in your NestJS application +- Setting up the required controllers and routes +- Implementing the authentication flow + +By following these provider-specific guides, you'll be able to complete the federated authentication setup and enable users to log in using their preferred social accounts. + +## How-To Guides + +### Implement FederatedUserLookupServiceInterface + +Create a service that implements `FederatedUserLookupServiceInterface`: + +```ts +// user.mock.ts +export const mockUser = { + id: 'abc', + email: 'me@dispostable.com', + username: 'me@dispostable.com', +} +``` + +```ts +// user-lookup.service.ts +import { Injectable } from '@nestjs/common'; +import { ReferenceEmail } from '@concepta/ts-core'; +import { FederatedUserLookupServiceInterface } from '@concepta/nestjs-federated'; +import { mockUser } from './user.mock'; + + +@Injectable() +export class UserLookupServiceFixture implements FederatedUserLookupServiceInterface { + async byId(id: string): ReturnType { + if (id === mockUser.id) { + return mockUser; + } else { + throw new Error(); + } + } + + async byEmail(email: ReferenceEmail): ReturnType { + return email === mockUser.email ? mockUser : null; + } +} +``` + +### Implement FederatedUserMutateServiceInterface + +Create a service that implements `FederatedUserMutateServiceInterface`: + +```ts +// user-mutate.service.ts +import { FederatedCredentialsInterface, FederatedUserMutateServiceInterface } from '@concepta/nestjs-federated'; +import { FederatedUserMutateInterface } from '@concepta/nestjs-federated/dist/interfaces/federated-user-mutate.interface'; +import { Injectable } from '@nestjs/common'; +import { mockUser } from './user.mock'; + +@Injectable() +export class UserMutateServiceFixture implements FederatedUserMutateServiceInterface { + async create(_object: FederatedUserMutateInterface): Promise { + return mockUser; + } +} +``` + +### Using federated with Rockets Github Module + +For detailed instructions on using the federated module with the Rockets GitHub +module, please refer to the [@concepta/nestjs-auth-github documentation](https://www.rockets.tools/reference/rockets/nestjs-auth-github/README). + +## Reference + +For detailed information on the properties, methods, and classes used in +the `@concepta/nestjs-federated`, please refer to the API documentation +available at +[FederatedModule API Documentation](https://www.rockets.tools/reference/rockets/nestjs-federated/README). +This documentation provides comprehensive details on the interfaces and +services that you can utilize to customize and extend the authentication +functionality within your NestJS application. + +## Explanation + +### Federated Services + +1. **User Creation and Association**: The federated service then takes over: + - It checks if a user associated with the provider (e.g., GitHub, Google, + Facebook) account already exists. + - If the user doesn't exist, it creates a new user account. + - It associates the provider with the user account, creating a + link between the user's application account and their provider identity. + +### Module Options Responsibilities + +The `FederatedOptionsInterface` defines the configuration options for the +federated module. Here are the responsibilities of each option: + +- **userLookupService**: This is an implementation of the + `FederatedUserLookupServiceInterface`. It is responsible for looking up users + based on various criteria such as user ID or email. This service ensures that + the application can retrieve user information from the database or any other + storage mechanism. + +- **userMutateService**: This is an implementation of the + `FederatedUserMutateServiceInterface`. It handles the creation and mutation + of user data. This service is crucial for managing user accounts, especially + when new users sign up via federated authentication or when existing user + data needs to be updated. + +By configuring these options, you can customize the behavior of the federated +module to suit your application's requirements, ensuring seamless integration +with multiple social authentication providers.