Skip to content
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

add whitelisting emails #285

Merged
merged 2 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ config.STATS_EXTERNAL_DASHBOARD_URL = process.env.STATS_EXTERNAL_DASHBOARD_URL


config.OIDC_PROVIDER_URL = process.env.OIDC_PROVIDER_URL
config.GRIST_API_KEY = process.env.GRIST_API_KEY
config.GRIST_API_DOMAINS_URL = process.env.GRIST_API_DOMAINS_URL
config.OIDC_CLIENT_ID = process.env.OIDC_CLIENT_ID
config.OIDC_CLIENT_SECRET = process.env.OIDC_CLIENT_SECRET
config.OIDC_ACR_VALUES = process.env.OIDC_ACR_VALUES
Expand Down
5 changes: 2 additions & 3 deletions controllers/createConfController.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,10 @@ const createConfWithDay = async (email, conferenceDay, userTimezoneOffset) => {
module.exports.createConf = async (req, res) => {
const confData = await oidcAuth.finishAuth(req)

const { email, durationInMinutes, conferenceDay, userTimezoneOffset } = confData
const { email, durationInMinutes, conferenceDay, userTimezoneOffset, error } = confData

if (!conferenceDay && !durationInMinutes) {
console.error("Login token contained no conferenceDay and no durationInMinutes. Cannot create conference.")
req.flash("error", "La conférence n'a pas pu être créée. Vous pouvez réessayer.")
req.flash("error", error || "La conférence n'a pas pu être créée. Vous pouvez réessayer.")
return res.redirect("/")
}

Expand Down
12 changes: 12 additions & 0 deletions lib/domains.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const config = require("../config")

module.exports.getWhitelistedDomains = async () => {
const URL = config.GRIST_API_DOMAINS_URL
const API_KEY = config.GRIST_API_KEY
const result = await fetch(URL, {headers: {Authorization: `Bearer ${API_KEY}`}})
const data = await result.json()
if(data.status !== "success") {
throw new Error("Error while fetching GRIST API")
}
return data.items
}
14 changes: 14 additions & 0 deletions lib/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,17 @@ module.exports.formatLocalTime = function(date) {
return date.getHours() + ":" + minutes + ":" + seconds
}

module.exports.extractEmailDomain = function(email) {
// Expression régulière pour valider une adresse email
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;

// Vérification si l'adresse email est valide
if (!emailRegex.test(email)) {
throw new Error("Adresse email invalide");
}

// Extraction du domaine avec un split
const domain = email.split("@")[1];

return domain;
}
40 changes: 40 additions & 0 deletions lib/format.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const { expect } = require("chai")
const sinon = require("sinon")

const extractEmailDomain = require("./format")

describe("format", function() {

describe("extractEmailDomain", () => {
test("devrait retourner le domaine d\"une adresse email valide", () => {
const email = "[email protected]";
const domain = extractEmailDomain(email);
expect(domain).toBe("example.com");
});

test("devrait retourner le domaine d\"une adresse email académique", () => {
const email = "[email protected]";
const domain = extractEmailDomain(email);
expect(domain).toBe("university.edu");
});

test("devrait lever une erreur pour une adresse email sans @", () => {
expect(() => {
extractEmailDomain("invalidEmail");
}).toThrow("Adresse email invalide");
});

test("devrait lever une erreur pour un domaine manquant", () => {
expect(() => {
extractEmailDomain("john.doe@");
}).toThrow("Domaine email invalide");
});

test("devrait lever une erreur pour une chaîne vide", () => {
expect(() => {
extractEmailDomain(");
}).toThrow("Adresse email invalide");
});
});

})
14 changes: 14 additions & 0 deletions lib/oidcAuth.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const { generators, Issuer } = require("openid-client")
const config = require("../config.js")
const urls = require("../urls")
const db = require("../lib/db")
const format = require("../lib/format")
const { getWhitelistedDomains } = require("./domains.js")

const urlCallback = urls.createConf

Expand Down Expand Up @@ -119,6 +121,18 @@ module.exports.finishAuth = async (req) => {
return { error: "L'identification a échoué. Entrez votre adresse mail ci-dessous pour recommencer." }
}
const email = userinfo.email

try {
const domain = format.extractEmailDomain(email)
const whitelistedDomains = await getWhitelistedDomains()
if(!whitelistedDomains.includes(domain)){
throw new Error(`The domain ${domain} is not whitelisted.`)
}
} catch(e){
console.error(`error when validating email ${email}`,e)
return { error: `L'adresse e-mail ${email} n'est pas autorisée à utiliser ce service. Si vous êtes agent de l'État, contactez-nous à [email protected]` }
}

const user = {id_token: tokenSet.id_token, state: request.state}

req.session.user = user
Expand Down
Loading