Skip to content

Commit

Permalink
feat: refactoring des access token pour embarquer l'uri complète (#807)
Browse files Browse the repository at this point in the history
* feat: refactoring des access token pour embarquer l'uri complète

* fix: remove fonction d'example

* fix: refactoring pour autoriser des options indéfinie dans le token

* fix: test

* fix: import in api.utils.test.ts

* fix: ajout de tests unitaires

* fix: tests

* fix: passage automatique du paramètre token

* fix: passage du token dans le header à la place de la querystring

* fix: tests

* fix: ajout du header authorization

* fix: gestion de endpoints mutltiples

* fix: update talismanrc

* fix: suppression de l'ajout auto du header pour l'access token

* fix: typing

* fix: tests + typing

---------

Co-authored-by: Kevin Barnoin <[email protected]>
  • Loading branch information
remy-auricoste and kevbarns authored Nov 16, 2023
1 parent c10da68 commit 62d9cb6
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 33 deletions.
12 changes: 8 additions & 4 deletions server/src/security/accessTokenService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import config from "@/config"

type SchemaWithSecurity = Pick<IRouteSchema, "method" | "path" | "params" | "querystring"> & WithSecurityScheme

type IScope<Schema extends SchemaWithSecurity> = {
export type IScope<Schema extends SchemaWithSecurity> = {
schema: Schema
options:
| "all"
Expand All @@ -23,6 +23,10 @@ type IScope<Schema extends SchemaWithSecurity> = {
}
}

export const generateScope = <Schema extends SchemaWithSecurity>(scope: IScope<Schema>): IScope<Schema> => {
return scope
}

export type IAccessToken<Schema extends SchemaWithSecurity = SchemaWithSecurity> = {
identity:
| {
Expand Down Expand Up @@ -52,14 +56,14 @@ function getAudience({
return `${method} ${generateUri(path, options, skipParamsReplacement)}`.toLowerCase()
}

export function generateAccessToken<Schema extends ISecuredRouteSchema>(
export function generateAccessToken(
user: IUserRecruteur | IAccessToken["identity"],
scopes: ReadonlyArray<IScope<Schema>>,
scopes: ReadonlyArray<IScope<ISecuredRouteSchema>>,
options: { expiresIn?: string } = {}
): string {
const audiences = scopesToAudiences(scopes)
const identity: IAccessToken["identity"] = "_id" in user ? { type: "IUserRecruteur", _id: user._id.toString(), email: user.email.toLowerCase() } : user
const data: IAccessToken<Schema> = {
const data: IAccessToken<ISecuredRouteSchema> = {
identity,
scopes,
}
Expand Down
18 changes: 9 additions & 9 deletions server/src/services/appLinks.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ import { IUserRecruteur } from "shared/models"
import { zRoutes } from "shared/routes"

import config from "@/config"
import { generateAccessToken } from "@/security/accessTokenService"
import { generateAccessToken, generateScope } from "@/security/accessTokenService"

export function createAuthMagicLinkToken(user: IUserRecruteur) {
return generateAccessToken(user, [
{
generateScope({
schema: zRoutes.post["/login/verification"],
options: {
params: undefined,
querystring: undefined,
},
resources: {},
},
}),
])
}

Expand All @@ -27,7 +27,7 @@ export function createValidationMagicLink(user: IUserRecruteur) {
const token = generateAccessToken(
user,
[
{
generateScope({
schema: zRoutes.post["/etablissement/validation"],
options: {
params: undefined,
Expand All @@ -36,7 +36,7 @@ export function createValidationMagicLink(user: IUserRecruteur) {
resources: {
user: [user._id.toString()],
},
},
}),
],
{
expiresIn: "30d",
Expand All @@ -49,14 +49,14 @@ export function createOptoutValidateMagicLink(email: string, siret: string) {
const token = generateAccessToken(
{ type: "cfa", email, siret },
[
{
generateScope({
schema: zRoutes.get["/optout/validate"],
options: {
params: undefined,
querystring: undefined,
},
resources: {},
},
}),
],
{
expiresIn: "45d",
Expand All @@ -69,7 +69,7 @@ export function createCfaUnsubscribeToken(email: string, siret: string) {
return generateAccessToken(
{ type: "cfa", email, siret },
[
{
generateScope({
schema: zRoutes.post["/etablissement/:establishment_siret/proposition/unsubscribe"],
options: {
params: {
Expand All @@ -78,7 +78,7 @@ export function createCfaUnsubscribeToken(email: string, siret: string) {
querystring: undefined,
},
resources: {},
},
}),
],
{
expiresIn: "30d",
Expand Down
18 changes: 9 additions & 9 deletions server/tests/unit/security/accessTokenService.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { zRoutes } from "shared/routes"
import { describe, expect, it } from "vitest"

import { generateAccessToken, parseAccessToken } from "../../../src/security/accessTokenService"
import { generateAccessToken, generateScope, parseAccessToken } from "../../../src/security/accessTokenService"

describe("accessTokenService", () => {
// called route
Expand All @@ -19,29 +19,29 @@ describe("accessTokenService", () => {
describe("valid tokens", () => {
it("should generate a token valid for a specific route", () => {
const token = generateAccessToken(user, [
{
generateScope({
schema,
resources: {},
options,
},
}),
])
expectTokenValid(token)
})
it("should generate a token valid for a generic route", () => {
const token = generateAccessToken(user, [
{
generateScope({
schema,
resources: {},
options: "all",
},
}),
])
expectTokenValid(token)
})
})
describe("invalid tokens", () => {
it("should detect an invalid token that has a different param", () => {
const token = generateAccessToken(user, [
{
generateScope({
schema,
resources: {},
options: {
Expand All @@ -50,17 +50,17 @@ describe("accessTokenService", () => {
},
querystring: undefined,
},
},
}),
])
expectTokenInvalid(token)
})
it("should detect an invalid token that is for a different route", () => {
const token = generateAccessToken(user, [
{
generateScope({
schema: zRoutes.post["/admin/users"],
resources: {},
options: "all",
},
}),
])
expectTokenInvalid(token)
})
Expand Down
11 changes: 0 additions & 11 deletions ui/utils/api.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,12 @@ async function optionsToFetchParams(method: RequestInit["method"], options: IReq
const { timeout, headers: addedHeaders } = fetchOptions

const headers = await getHeaders(options)
const accessToken = getAccessToken()

if (addedHeaders) {
Object.entries(addedHeaders).forEach(([key, value]) => {
headers.append(key, value)
})
}
if (accessToken && !headers.has("authorization")) {
headers.append("authorization", `Bearer ${accessToken}`)
}

let body: BodyInit | undefined = undefined
if ("body" in options && method !== "GET") {
Expand Down Expand Up @@ -83,13 +79,6 @@ async function getHeaders(options: IRequestOptions) {

const removeAtEnd = (url: string, removed: string): string => (url.endsWith(removed) ? url.slice(0, -removed.length) : url)

const getAccessToken = () => {
if (typeof window !== "undefined") {
const token = new URLSearchParams(window.location.search).get("token")
return token
}
}

export function generateUrl(path: string, options: WithQueryStringAndPathParam = {}): string {
const params = "params" in options ? options.params : {}
const querystring = "querystring" in options ? options.querystring : {}
Expand Down

0 comments on commit 62d9cb6

Please sign in to comment.