Как создать API на основе ролей с аутентификацией Firebase
Опубликовано: 2022-03-11В этом руководстве мы создадим REST API для управления пользователями и ролями с помощью Firebase и Node.js. Кроме того, мы увидим, как использовать API для авторизации (или запрета) того, какие пользователи могут получить доступ к определенным ресурсам.
Введение
Почти каждое приложение требует определенного уровня системы авторизации. В некоторых случаях достаточно проверить набор имени пользователя/пароля с помощью нашей таблицы Users, но часто нам нужна более детальная модель разрешений, чтобы позволить определенным пользователям получать доступ к определенным ресурсам и ограничивать их от других. Построение системы для поддержки последнего не является тривиальной задачей и может занять очень много времени. В этом руководстве мы узнаем, как создать API аутентификации на основе ролей с помощью Firebase, что поможет нам быстро приступить к работе.
Ролевая аутентификация
В этой модели авторизации доступ предоставляется ролям, а не конкретным пользователям, и пользователь может иметь одну или несколько ролей в зависимости от того, как вы разрабатываете свою модель разрешений. Ресурсы, с другой стороны, требуют определенных ролей, чтобы пользователь мог их выполнять.
Firebase
Аутентификация Firebase
В двух словах, Firebase Authentication — это расширяемая система аутентификации на основе токенов, которая обеспечивает готовую интеграцию с наиболее распространенными поставщиками, такими как Google, Facebook и Twitter, среди прочих.
Это позволяет нам использовать настраиваемые утверждения, которые мы будем использовать для создания гибкого API на основе ролей.
Мы можем установить любое значение JSON в утверждениях (например, { role: 'admin' }
или { role: 'manager' }
).
После установки пользовательские утверждения будут включены в токен, который генерирует Firebase, и мы можем прочитать значение для управления доступом.
Он также поставляется с очень щедрой бесплатной квотой, которой в большинстве случаев будет более чем достаточно.
Функции Firebase
Функции — это полностью управляемая бессерверная платформа. Нам просто нужно написать наш код в Node.js и развернуть его. Firebase позаботится о масштабировании инфраструктуры по требованию, настройке сервера и многом другом. В нашем случае мы будем использовать его для создания нашего API и предоставления его через HTTP в Интернете.
Firebase позволяет нам устанавливать приложения express.js
в качестве обработчиков для разных путей — например, вы можете создать приложение Express и подключить его к /mypath
, и все запросы, поступающие на этот маршрут, будут обрабатываться настроенным app
.
Из контекста функции у вас есть доступ ко всему API аутентификации Firebase с помощью Admin SDK.
Вот как мы создадим пользовательский API.
Что мы построим
Итак, прежде чем мы начнем, давайте посмотрим, что мы будем строить. Мы собираемся создать REST API со следующими конечными точками:
Глагол HTTP | Дорожка | Описание | Авторизация |
---|---|---|---|
ПОЛУЧАТЬ | /пользователи | Список всех пользователей | Доступ имеют только администраторы и менеджеры |
СООБЩЕНИЕ | /пользователи | Создает нового пользователя | Доступ имеют только администраторы и менеджеры |
ПОЛУЧАТЬ | /пользователи/: идентификатор | Получает пользователя :id | Администраторы, менеджеры и тот же пользователь, что и :id, имеют доступ |
ПЛАСТЫРЬ | /пользователи/: идентификатор | Обновляет пользователя :id | Администраторы, менеджеры и тот же пользователь, что и :id, имеют доступ |
УДАЛЯТЬ | /пользователи/: идентификатор | Удаляет пользователя :id | Администраторы, менеджеры и тот же пользователь, что и :id, имеют доступ |
Каждая из этих конечных точек будет обрабатывать аутентификацию, проверять авторизацию, выполнять соответствующую операцию и, наконец, возвращать значимый HTTP-код.
Мы создадим функции проверки подлинности и авторизации, необходимые для проверки маркера, и проверим, содержат ли утверждения необходимую роль для выполнения операции.
Создание API
Для создания API нам понадобится:
- Проект Firebase
- установлены
firebase-tools
firebase
Сначала войдите в Firebase:
firebase login
Затем инициализируйте проект Functions:
firebase init ? Which Firebase CLI features do you want to set up for this folder? ... (O) Functions: Configure and deploy Cloud Functions ? Select a default Firebase project for this directory: {your-project} ? What language would you like to use to write Cloud Functions? TypeScript ? Do you want to use TSLint to catch probable bugs and enforce style? Yes ? Do you want to install dependencies with npm now? Yes
На этом этапе у вас будет папка «Функции» с минимальной настройкой для создания функций Firebase.
В src/index.ts
есть пример helloWorld
, который вы можете раскомментировать, чтобы убедиться, что ваши функции работают. Затем вы можете cd functions
и запустить npm run serve
. Эта команда перенесет код и запустит локальный сервер.
Вы можете проверить результаты по адресу http://localhost:5000/{your-project}/us-central1/helloWorld.
Обратите внимание, что функция отображается по пути, определенному как ее имя в 'index.ts: 'helloWorld'
.
Создание HTTP-функции Firebase
Теперь давайте напишем наш API. Мы собираемся создать функцию http Firebase и подключить ее к пути /api
.
Сначала установите npm install express
.
На src/index.ts
мы будем:
- Инициализируйте модуль Firebase-admin SDK с помощью
admin.initializeApp();
- Установите приложение Express в качестве обработчика нашей конечной точки
api
https.
import * as functions from 'firebase-functions'; import * as admin from 'firebase-admin'; import * as express from 'express'; admin.initializeApp(); const app = express(); export const api = functions.https.onRequest(app);
Теперь все запросы к /api
будут обрабатываться экземпляром app
.
Следующее, что мы сделаем, — настроим экземпляр app
для поддержки CORS и добавим промежуточное ПО анализатора тела JSON. Таким образом, мы можем делать запросы с любого URL-адреса и анализировать запросы в формате JSON.
Сначала мы установим необходимые зависимости.
npm install --save cors body-parser
npm install --save-dev @types/cors
А потом:
//... import * as cors from 'cors'; import * as bodyParser from 'body-parser'; //... const app = express(); app.use(bodyParser.json()); app.use(cors({ origin: true })); export const api = functions.https.onRequest(app);
Наконец, мы настроим маршруты, которые будет обрабатывать app
.
//... import { routesConfig } from './users/routes-config'; //… app.use(cors({ origin: true })); routesConfig(app) export const api = functions.https.onRequest(app);
Функции Firebase позволяют нам установить приложение Express в качестве обработчика и любой путь после того, который вы установили в functions.https.onRequest(app);
— в данном случае api
— также будет обрабатываться app
. Это позволяет нам писать определенные конечные точки, такие как api/users
и устанавливать обработчик для каждой HTTP-команды, что мы и сделаем дальше.
Создадим файл src/users/routes-config.ts
Здесь мы установим обработчик create
в POST '/users'
import { Application } from "express"; import { create} from "./controller"; export function routesConfig(app: Application) { app.post('/users', create ); }
Теперь мы создадим файл src/users/controller.ts
.
В этой функции мы сначала проверяем наличие всех полей в теле запроса, а затем создаем пользователя и устанавливаем настраиваемые утверждения.
Мы просто передаем { role }
в setCustomUserClaims
— остальные поля уже заданы Firebase.
Если ошибок не возникает, мы возвращаем код 201 с uid
созданного пользователя.
import { Request, Response } from "express"; import * as admin from 'firebase-admin' export async function create(req: Request, res: Response) { try { const { displayName, password, email, role } = req.body if (!displayName || !password || !email || !role) { return res.status(400).send({ message: 'Missing fields' }) } const { uid } = await admin.auth().createUser({ displayName, password, email }) await admin.auth().setCustomUserClaims(uid, { role }) return res.status(201).send({ uid }) } catch (err) { return handleError(res, err) } } function handleError(res: Response, err: any) { return res.status(500).send({ message: `${err.code} - ${err.message}` }); }
Теперь давайте защитим обработчик, добавив авторизацию. Для этого мы добавим пару обработчиков в нашу конечную точку create
. С помощью express.js
вы можете установить цепочку обработчиков, которые будут выполняться по порядку. Внутри обработчика вы можете выполнить код и передать его обработчику next()
или вернуть ответ. Что мы сделаем, так это сначала аутентифицируем пользователя, а затем проверим, авторизован ли он для выполнения.
В файле src/users/routes-config.ts
:
//... import { isAuthenticated } from "../auth/authenticated"; import { isAuthorized } from "../auth/authorized"; export function routesConfig(app: Application) { app.post('/users', isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'] }), create ); }
Давайте создадим файлы src/auth/authenticated.ts
.
В этой функции мы проверим наличие токена носителя authorization
в заголовке запроса. Затем мы декодируем его с помощью admin.auth().verifyidToken()
и сохраняем uid
, role
и email
пользователя в переменной res.locals
, которую позже будем использовать для проверки авторизации.
В случае, если токен недействителен, мы возвращаем клиенту ответ 401:
import { Request, Response } from "express"; import * as admin from 'firebase-admin' export async function isAuthenticated(req: Request, res: Response, next: Function) { const { authorization } = req.headers if (!authorization) return res.status(401).send({ message: 'Unauthorized' }); if (!authorization.startsWith('Bearer')) return res.status(401).send({ message: 'Unauthorized' }); const split = authorization.split('Bearer ') if (split.length !== 2) return res.status(401).send({ message: 'Unauthorized' }); const token = split[1] try { const decodedToken: admin.auth.DecodedIdToken = await admin.auth().verifyIdToken(token); console.log("decodedToken", JSON.stringify(decodedToken)) res.locals = { ...res.locals, uid: decodedToken.uid, role: decodedToken.role, email: decodedToken.email } return next(); } catch (err) { console.error(`${err.code} - ${err.message}`) return res.status(401).send({ message: 'Unauthorized' }); } }
Теперь давайте создадим файл src/auth/authorized.ts
.
В этом обработчике мы извлекаем информацию о пользователе из res.locals
, которую мы установили ранее, и проверяем, есть ли у него роль, необходимая для выполнения операции, или, в случае, если операция позволяет выполняться тому же пользователю, мы проверяем, что идентификатор в параметрах запроса такой же, как и в токене авторизации. Если у пользователя нет требуемой роли, мы вернем 403.
import { Request, Response } from "express"; export function isAuthorized(opts: { hasRole: Array<'admin' | 'manager' | 'user'>, allowSameUser?: boolean }) { return (req: Request, res: Response, next: Function) => { const { role, email, uid } = res.locals const { id } = req.params if (opts.allowSameUser && id && uid === id) return next(); if (!role) return res.status(403).send(); if (opts.hasRole.includes(role)) return next(); return res.status(403).send(); } }
С помощью этих двух методов мы сможем аутентифицировать запросы и авторизовать их с учетом role
во входящем токене. Это здорово, но поскольку Firebase не позволяет нам устанавливать пользовательские утверждения из консоли проекта, мы не сможем выполнить ни одну из этих конечных точек. Чтобы обойти это, мы можем создать пользователя root из Firebase Authentication Console.
И установите сравнение электронной почты в коде. Теперь при запуске запросов от этого пользователя мы сможем выполнять все операции.
//... const { role, email, uid } = res.locals const { id } = req.params if (email === '[email protected]') return next(); //...
Теперь давайте добавим остальные операции CRUD в src/users/routes-config.ts
.
Для операций по получению или обновлению одного пользователя, которому отправляется параметр :id
, мы также разрешаем тому же пользователю выполнять операцию.
export function routesConfig(app: Application) { //.. // lists all users app.get('/users', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'] }), all ]); // get :id user app.get('/users/:id', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'], allowSameUser: true }), get ]); // updates :id user app.patch('/users/:id', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'], allowSameUser: true }), patch ]); // deletes :id user app.delete('/users/:id', [ isAuthenticated, isAuthorized({ hasRole: ['admin', 'manager'] }), remove ]); }
И на src/users/controller.ts
. В этих операциях мы используем SDK администратора для взаимодействия с аутентификацией Firebase и выполнения соответствующих операций. Как и ранее при create
операции, мы возвращаем осмысленный HTTP-код для каждой операции.
Для операции обновления мы проверяем все имеющиеся поля и переопределяем customClaims
теми, которые отправлены в запросе:
//.. export async function all(req: Request, res: Response) { try { const listUsers = await admin.auth().listUsers() const users = listUsers.users.map(mapUser) return res.status(200).send({ users }) } catch (err) { return handleError(res, err) } } function mapUser(user: admin.auth.UserRecord) { const customClaims = (user.customClaims || { role: '' }) as { role?: string } const role = customClaims.role ? customClaims.role : '' return { uid: user.uid, email: user.email || '', displayName: user.displayName || '', role, lastSignInTime: user.metadata.lastSignInTime, creationTime: user.metadata.creationTime } } export async function get(req: Request, res: Response) { try { const { id } = req.params const user = await admin.auth().getUser(id) return res.status(200).send({ user: mapUser(user) }) } catch (err) { return handleError(res, err) } } export async function patch(req: Request, res: Response) { try { const { id } = req.params const { displayName, password, email, role } = req.body if (!id || !displayName || !password || !email || !role) { return res.status(400).send({ message: 'Missing fields' }) } await admin.auth().updateUser(id, { displayName, password, email }) await admin.auth().setCustomUserClaims(id, { role }) const user = await admin.auth().getUser(id) return res.status(204).send({ user: mapUser(user) }) } catch (err) { return handleError(res, err) } } export async function remove(req: Request, res: Response) { try { const { id } = req.params await admin.auth().deleteUser(id) return res.status(204).send({}) } catch (err) { return handleError(res, err) } } //...
Теперь мы можем запустить функцию локально. Для этого сначала вам нужно настроить ключ учетной записи, чтобы иметь возможность локального подключения к API авторизации. Затем запустите:

npm run serve
Развернуть API
Здорово! Теперь, когда мы написали API на основе ролей, мы можем развернуть его в Интернете и начать использовать. Развернуть с помощью Firebase очень просто, нам просто нужно запустить firebase deploy
. После завершения развертывания мы можем получить доступ к нашему API по опубликованному URL-адресу.
Вы можете проверить URL-адрес API по адресу https://console.firebase.google.com/u/0/project/{your-project}/functions/list.
В моем случае это [https://us-central1-joaq-lab.cloudfunctions.net/api].
Использование API
После развертывания нашего API у нас есть несколько способов его использования — в этом руководстве я расскажу, как использовать его через Postman или из приложения Angular.
Если мы введем URL-адрес списка всех пользователей ( /api/users
) в любом браузере, мы получим следующее:
Причина этого в том, что при отправке запроса из браузера мы выполняем запрос GET без заголовков аутентификации. Это означает, что наш API действительно работает так, как ожидалось!
Наш API защищен с помощью токенов. Чтобы сгенерировать такой токен, нам нужно вызвать клиентский SDK Firebase и войти в систему с действительными учетными данными пользователя/пароля. В случае успеха Firebase отправит токен обратно в ответ, который мы затем можем добавить в заголовок любого следующего запроса, который мы хотим выполнить.
Из углового приложения
В этом уроке я просто рассмотрю важные части, чтобы использовать API из приложения Angular. Доступ к полному репозиторию можно получить здесь, и если вам нужно пошаговое руководство по созданию приложения Angular и настройке @angular/fire для использования, вы можете проверить этот пост.
Итак, вернемся к входу в систему. У нас будет SignInComponent
с <form>
, чтобы пользователь мог ввести имя пользователя и пароль.
//... <form [formGroup]="form"> <div class="form-group"> <label>Email address</label> <input type="email" formControlName="email" class="form-control" placeholder="Enter email"> </div> <div class="form-group"> <label>Password</label> <input type="password" formControlName="password" class="form-control" placeholder="Password"> </div> </form> //...
А в классе мы подписываемся на signInWithEmailAndPassword
с помощью сервиса AngularFireAuth
.
//... form: FormGroup = new FormGroup({ email: new FormControl(''), password: new FormControl('') }) constructor( private afAuth: AngularFireAuth ) { } async signIn() { try { const { email, password } = this.form.value await this.afAuth.auth.signInWithEmailAndPassword(email, password) } catch (err) { console.log(err) } } //..
На этом этапе мы можем войти в наш проект Firebase.
И когда мы проверяем сетевые запросы в DevTools, мы видим, что Firebase возвращает токен после проверки нашего пользователя и пароля.
Этот токен мы будем использовать для отправки запроса нашего заголовка к API, который мы создали. Один из способов добавить токен ко всем запросам — использовать HttpInterceptor
.
В этом файле показано, как получить токен из AngularFireAuth
и добавить его в запрос заголовка. Затем мы предоставляем файл перехватчика в AppModule.
http-interceptors/auth-token.interceptor.ts
@Injectable({ providedIn: 'root' }) export class AuthTokenHttpInterceptor implements HttpInterceptor { constructor( private auth: AngularFireAuth ) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return this.auth.idToken.pipe( take(1), switchMap(idToken => { let clone = req.clone() if (idToken) { clone = clone.clone({ headers: req.headers.set('Authorization', 'Bearer ' + idToken) }); } return next.handle(clone) }) ) } } export const AuthTokenHttpInterceptorProvider = { provide: HTTP_INTERCEPTORS, useClass: AuthTokenHttpInterceptor, multi: true }
app.module.ts
@NgModule({ //.. providers: [ AuthTokenHttpInterceptorProvider ] //... }) export class AppModule { }
Как только перехватчик установлен, мы можем делать запросы к нашему API из httpClient
. Например, вот UsersService
, где мы вызываем список всех пользователей, получаем пользователя по его идентификатору, создаем пользователя и обновляем пользователя.
//… export type CreateUserRequest = { displayName: string, password: string, email: string, role: string } export type UpdateUserRequest = { uid: string } & CreateUserRequest @Injectable({ providedIn: 'root' }) export class UserService { private baseUrl = '{your-functions-url}/api/users' constructor( private http: HttpClient ) { } get users$(): Observable<User[]> { return this.http.get<{ users: User[] }>(`${this.baseUrl}`).pipe( map(result => { return result.users }) ) } user$(id: string): Observable<User> { return this.http.get<{ user: User }>(`${this.baseUrl}/${id}`).pipe( map(result => { return result.user }) ) } create(user: CreateUserRequest) { return this.http.post(`${this.baseUrl}`, user) } edit(user: UpdateUserRequest) { return this.http.patch(`${this.baseUrl}/${user.uid}`, user) } }
Теперь мы можем вызвать API, чтобы получить вошедшего в систему пользователя по его идентификатору и перечислить всех пользователей из компонента следующим образом:
//... <div *ngIf="user$ | async; let user" class="col-12"> <div class="d-flex justify-content-between my-3"> <h4> Me </h4> </div> <ul class="list-group"> <li class="list-group-item d-flex justify-content-between align-items-center"> <div> <h5 class="mb-1">{{user.displayName}}</h5> <small>{{user.email}}</small> </div> <span class="badge badge-primary badge-pill">{{user.role?.toUpperCase()}}</span> </li> </ul> </div> <div class="col-12"> <div class="d-flex justify-content-between my-3"> <h4> All Users </h4> </div> <ul *ngIf="users$ | async; let users" class="list-group"> <li *ngFor="let user of users" class="list-group-item d-flex justify-content-between align-items-center"> <div> <h5 class="mb-1">{{user.displayName}}</h5> <small class="d-block">{{user.email}}</small> <small class="d-block">{{user.uid}}</small> </div> <span class="badge badge-primary badge-pill">{{user.role?.toUpperCase()}}</span> </li> </ul> //...
//... users$: Observable<User[]> user$: Observable<User> constructor( private userService: UserService, private userForm: UserFormService, private modal: NgbModal, private afAuth: AngularFireAuth ) { } ngOnInit() { this.users$ = this.userService.users$ this.user$ = this.afAuth.user.pipe( filter(user => !!user), switchMap(user => this.userService.user$(user.uid)) ) } //...
И вот результат.
Обратите внимание, что если мы войдем в систему с помощью пользователя с role=user
, будет отображаться только раздел Me.
И мы получим 403 в сетевом инспекторе. Это связано с ограничением, которое мы установили ранее в API, чтобы разрешить только «Администраторам» перечислять всех пользователей.
Теперь давайте добавим функции «создать пользователя» и «редактировать пользователя». Для этого давайте сначала создадим UserFormComponent
и UserFormService
.
<ng-container *ngIf="user$ | async"></ng-container> <div class="modal-header"> <h4 class="modal-title">{{ title$ | async}}</h4> <button type="button" class="close" (click)="dismiss()"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form [formGroup]="form" (ngSubmit)="save()"> <div class="form-group"> <label>Email address</label> <input type="email" formControlName="email" class="form-control" placeholder="Enter email"> </div> <div class="form-group"> <label>Password</label> <input type="password" formControlName="password" class="form-control" placeholder="Password"> </div> <div class="form-group"> <label>Display Name</label> <input type="string" formControlName="displayName" class="form-control" placeholder="Enter display name"> </div> <div class="form-group"> <label>Role</label> <select class="custom-select" formControlName="role"> <option value="admin">Admin</option> <option value="manager">Manager</option> <option value="user">User</option> </select> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-outline-danger" (click)="dismiss()">Cancel</button> <button type="button" class="btn btn-primary" (click)="save()">Save</button> </div>
@Component({ selector: 'app-user-form', templateUrl: './user-form.component.html', styleUrls: ['./user-form.component.scss'] }) export class UserFormComponent implements OnInit { form = new FormGroup({ uid: new FormControl(''), email: new FormControl(''), displayName: new FormControl(''), password: new FormControl(''), role: new FormControl(''), }); title$: Observable<string>; user$: Observable<{}>; constructor( public modal: NgbActiveModal, private userService: UserService, private userForm: UserFormService ) { } ngOnInit() { this.title$ = this.userForm.title$; this.user$ = this.userForm.user$.pipe( tap(user => { if (user) { this.form.patchValue(user); } else { this.form.reset({}); } }) ); } dismiss() { this.modal.dismiss('modal dismissed'); } save() { const { displayName, email, role, password, uid } = this.form.value; this.modal.close({ displayName, email, role, password, uid }); } }
import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' }) export class UserFormService { _BS = new BehaviorSubject({ title: '', user: {} }); constructor() { } edit(user) { this._BS.next({ title: 'Edit User', user }); } create() { this._BS.next({ title: 'Create User', user: null }); } get title$() { return this._BS.asObservable().pipe( map(uf => uf.title) ); } get user$() { return this._BS.asObservable().pipe( map(uf => uf.user) ); } }
Вернемся к основному компоненту и добавим кнопки для вызова этих действий. В этом случае «Редактировать пользователя» будет доступно только вошедшему в систему пользователю. Вы можете пойти дальше и добавить функциональность для редактирования других пользователей, если вам нужно!
//... <div class="d-flex justify-content-between my-3"> <h4> Me </h4> <button class="btn btn-primary" (click)="edit(user)"> Edit Profile </button> </div> //... <div class="d-flex justify-content-between my-3"> <h4> All Users </h4> <button class="btn btn-primary" (click)="create()"> New User </button> </div> //...
//... create() { this.userForm.create(); const modalRef = this.modal.open(UserFormComponent); modalRef.result.then(user => { this.userService.create(user).subscribe(_ => { console.log('user created'); }); }).catch(err => { }); } edit(userToEdit) { this.userForm.edit(userToEdit); const modalRef = this.modal.open(UserFormComponent); modalRef.result.then(user => { this.userService.edit(user).subscribe(_ => { console.log('user edited'); }); }).catch(err => { }); }
От почтальона
Postman — это инструмент для создания и выполнения запросов к API. Таким образом, мы можем имитировать вызов нашего API из любого клиентского приложения или другой службы.
Мы продемонстрируем, как отправить запрос на получение списка всех пользователей.
Открыв инструмент, мы устанавливаем URL-адрес https://us-central1-{your-project}.cloudfunctions.net/api/users:
Затем на вкладке авторизация мы выбираем Bearer Token и устанавливаем значение, которое мы ранее извлекли из Dev Tools.
Заключение
Поздравляем! Вы прошли весь учебник и научились создавать API на основе ролей пользователей в Firebase.
Мы также рассмотрели, как использовать его из приложения Angular и Postman.
Напомним самое важное:
- Firebase позволяет быстро приступить к работе с помощью API аутентификации корпоративного уровня, который вы сможете расширить позже.
- Почти каждый проект требует авторизации — если вам нужно контролировать доступ с помощью ролевой модели, Firebase Authentication позволяет очень быстро приступить к работе.
- Ролевая модель основана на проверке ресурсов, которые запрашиваются у пользователей с определенными ролями, а не у конкретных пользователей.
- Используя приложение Express.js в Firebase Function, мы можем создать REST API и настроить обработчики для аутентификации и авторизации запросов.
- Используя встроенные настраиваемые утверждения, вы можете создать API аутентификации на основе ролей и защитить свое приложение.
Вы можете прочитать больше об аутентификации Firebase здесь. И если вы хотите использовать роли, которые мы определили, вы можете использовать хелперы @angular/fire.