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

Connexion à l'espace utilisateur (mode distant) #421

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7fb737c
test sso
lowzonenose Oct 30, 2024
711b00f
impl. iam
lowzonenose Oct 31, 2024
f6d2fe5
Merge branch 'main' into feature/connexion
lowzonenose Oct 31, 2024
0f31c4c
Environnement + fonction generique fetch
lowzonenose Nov 3, 2024
6453a05
gestion env + https
lowzonenose Nov 4, 2024
6e6615b
mode bouchon en attendant de resoudre le token
lowzonenose Nov 5, 2024
0419bfd
refactor avec routes Login & Logout
lowzonenose Nov 11, 2024
ade1b17
refactor
lowzonenose Nov 13, 2024
11d1d75
Mode mock sur les appels IAM ou API
lowzonenose Nov 15, 2024
5c0ed38
Merge branch 'main' into feature/connexion
lowzonenose Nov 15, 2024
75d1ec2
Storage session token
lowzonenose Nov 15, 2024
218507a
Service User
lowzonenose Nov 18, 2024
8750f93
Menu des favoris
lowzonenose Nov 18, 2024
a332341
Merge branch 'main' into feature/connexion
lowzonenose Nov 22, 2024
8bc8565
Fix
lowzonenose Nov 26, 2024
e456289
Fix server vite + server aleternatif
lowzonenose Nov 26, 2024
df27cef
Fix response UsersMe
lowzonenose Nov 27, 2024
fea010e
utilisation du client oauth2
lowzonenose Dec 3, 2024
e118f32
Optimisation du code
lowzonenose Dec 3, 2024
790e0cd
fix header ref
lowzonenose Dec 3, 2024
f00a438
fix header ref
lowzonenose Dec 3, 2024
1b2447e
Merge branch 'main' into feature/connexion
lowzonenose Dec 3, 2024
0b92502
Fix garde la connexion sur plusieurs onglets
lowzonenose Dec 7, 2024
bd75b7d
fix masque l'utilisateur si souci de connexion
lowzonenose Dec 7, 2024
a362712
Fix message type alerte (warning) si exception dans la connexion
lowzonenose Dec 7, 2024
79191bd
Fix message type alerte (error)
lowzonenose Dec 7, 2024
fb19189
Secrets de connexion pour le deploiement sur la demo et docker
lowzonenose Dec 8, 2024
13a8e6b
Cohabiter les 2 modes d'authentification : local et remote (cartes.go…
lowzonenose Dec 11, 2024
539c749
fixme pour le refreshtoken
lowzonenose Dec 11, 2024
50914ce
token expire 12h..., refresh ?
lowzonenose Dec 12, 2024
4bec864
Fix logout
lowzonenose Dec 13, 2024
0b3e6a7
fix sur l'appel d'un nouveau token
lowzonenose Dec 13, 2024
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
Prev Previous commit
Next Next commit
refactor
lowzonenose committed Nov 13, 2024
commit ade1b17f67d2c29a88ad382342eb9b138b6b83e4
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -66,6 +66,7 @@
"npm-run-all2": "^6.1.2",
"oh-vue-icons": "1.0.0-rc3",
"pinia": "^2.1.7",
"pinia-plugin-store": "^2.2.9",
"rimraf": "^5.0.5",
"sass": "^1.76.0",
"typescript": "~5.4.0",
13 changes: 13 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -11,6 +11,9 @@ import { createPinia } from 'pinia'
import { createLogger } from 'vue-logger-plugin'
// plugin local
import { createEulerian } from './plugins/Eulerian'
import { createServices } from './plugins/Services'

import { storePlugin } from 'pinia-plugin-store'

import App from './App.vue'
import router from './router/index'
@@ -23,6 +26,8 @@ addIcons(...Object.values(icons)) // Autoimporté grâce à ohVueIconAutoimportP
// https://vitejs.dev/guide/env-and-mode.html#node-env-and-modes
const isProduction = (import.meta.env.MODE === "production")

const services = createServices();

const eulerian = createEulerian({
verbose : !isProduction, // option du plugin
domain: "acwg.cartes.gouv.fr", // OBLIGATOIRE :domaine de tracking Eulerian
@@ -38,11 +43,19 @@ const logger = createLogger({
level: isProduction ? 'error' : 'debug',
callerInfo: true
})

const pinia = createPinia()

const store = storePlugin({
stores: ['service'],
storage: localStorage,
});
pinia.use(store);

createApp(App)
.use(pinia)
.use(router)
.use(logger)
.use(eulerian)
.use(services)
.mount('#app')
25 changes: 25 additions & 0 deletions src/plugins/Services.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { inject } from 'vue';
import Services from '@/services/Services';

const servicesSymbol = Symbol('vue-services-plugin');

export class PluginServices extends Services {
/**
* Installation du plugin
* @param {*} app
*/
install(app) {
app.provide(servicesSymbol, this);
app.config.globalProperties.$services = this;
app.provide('services', this);
}
}

export function createServices(options) {
return new PluginServices(options);
}

export function useServices() {
const services = inject(servicesSymbol);
return services;
}
132 changes: 22 additions & 110 deletions src/services/serviceConnection.js → src/services/ServiceConnection.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useRequest } from '@/services/request';
import Users from '@/services/serviceUsers';

// INFO
// recuperation des informations sur l'env
@@ -11,47 +10,21 @@ const IAM_CLIENT_SECRET = import.meta.env.IAM_CLIENT_SECRET;
/**
* @description
* Classe de service de connexion à la geoplateforme
* cf. {@link https://developer.okta.com/blog/2018/04/10/oauth-authorization-code-grant-type}
* ou {@link https://stackoverflow.blog/2022/04/14/the-authorization-code-grant-in-excruciating-detail/#h2-97e8b796eefc0}
*
* @see env
* @see serviceStore
* @example
* import Service from '@/services/serviceConnection';
* var service = new Service();
* // requêtes
* service.getAccessLogin();
* service.getAccessToken();
* service.getAccessLogout();
* service.getAccessUser();
* Service.getAccessLogin();
* Service.getAccessToken();
* Service.getAccessLogout();
* // propriétés
* service.authenticated;
* service.token;
* service.state;
* service.user;
* Service.authenticated;
* Service.token;
* Service.state;
* ...
*/
class Service {

/** Constructeur */
constructor (options) {

this.options = options || {};

/** authentification */
this.authenticated = false;
/** token */
this.token = null;
/** state session */
this.session = null;
/** code */
this.code = null;
/** erreurs IAM */
this.error = {};

this.url = encodeURI(location.origin + location.pathname);

return this;
}
var Connexion = {

/////////////
// requêtes
@@ -76,21 +49,21 @@ class Service {
* code=168e7dd8-ae1f-4f8b-99f7-ae0aac066067.968321a6-385e-4058-a17a-571ab08303bd.3038d336-2dfa-4c2e-954e-090ee781ed7f
*
*/
getAccessLogin () {
getAccessLogin : function () {
// INFO
// La réponse fournit le 'code',
// et il doit être utiliser pour obtenir le token
// cf. getAccessToken()

const url = location.pathname.includes("login") ? this.url : this.url + "/login";
const url = this.url.includes("login") ? this.url : this.url + "/login";
return `${IAM_URL}/realms/${IAM_REALM}/protocol/openid-connect/auth?
scope=openid%20profile%20email&
approval_prompt=auto&
response_type=code&
state=xcoiv98y2kd22vusuye3kch&
redirect_uri=${url}&
client_id=${IAM_CLIENT_ID}`.replace(/ /g, '');
}
},

/**
* IAM pour se deconnecter
@@ -108,19 +81,19 @@ class Service {
* http://localhost:5173/cartes.gouv.fr-entree-carto/?
* session_state=968321a6-385e-4058-a17a-571ab08303bd
*/
getAccessLogout () {
getAccessLogout : function () {
// INFO
// La reponse fournit la 'session',
// et la session doit être identique à celle issue de login

const url = location.pathname.includes("logout") ? this.url : this.url + "/logout";
const url = this.url.includes("logout") ? this.url : this.url + "/logout";
return `${IAM_URL}/realms/${IAM_REALM}/protocol/openid-connect/logout?
scope=openid%20profile%20email&
approval_prompt=auto&
response_type=code&
post_logout_redirect_uri=${url}?session_state=${this.session}&
client_id=${IAM_CLIENT_ID}`.replace(/ /g, '');
}
},

/**
* IAM pour obtenir le token
@@ -146,7 +119,7 @@ class Service {
* ...
* }
*/
getAccessToken () {
getAccessToken : function () {

// curl --request POST --url "https://sso.geopf.fr/realms/geoplateforme/protocol/openid-connect/token" --header "content-type: application/x-www-form-urlencoded" -d 'client_id='cartes-gouv-dev'&client_secret='heH4uOv2ihsxn2ziE8pyNBOI6dbCy1sp'&grant_type=client_credentials'
// fetch("https://sso.geopf.fr/realms/geoplateforme/protocol/openid-connect/token", {
@@ -190,65 +163,7 @@ class Service {
"scope": "profile email"
});
}) : useRequest(url, settings);
}

/////////////////
// méthod public
/////////////////

/**
* Permet de valider la connexion en obtenant un token
*/
isAccessValided () {
// si login via IAM, on récupère le code dans l'url
const queryString = location.search;
const urlParams = new URLSearchParams(queryString);
// parametres
var code = urlParams.get('code');
var session = urlParams.get('session_state');
var error = urlParams.get('error');
// IAM login
if (code && session) {
this.session = session;
this.code = code;
this.getAccessToken()
.then((data) => {
this.authenticated = true;
this.token = data;
this.addTokenStorage();
return data;
})
// .then((data) => {
// var token = data.access_token;
// this.getUserMe(token)
// .then((data) => {
// this.user = data;
// });
// })
.catch((e) => {
console.error(e.message);
});
}
// IAM logout
// FIXME logout doit fournir la session !!!
if (!code && session && session === this.session) {
this.session = null;
this.code = null;
this.authenticated = false;
this.token = null;
this.removeTokenStorage();
this.user = {};
this.error = {};
}
// Error
if (error) {
// FIXME où afficher l'erreur ?
this.error = {
name: error,
message: urlParams.get('error_description')
};
}
}
},

//////////////////
// méthod private
@@ -270,13 +185,13 @@ class Service {
* }
* }
*/
getTokenStorage () {
getTokenStorage : function () {
return JSON.parse(localStorage.getItem("auth"));
}
},
/**
* Ajoute le token d'authentification du localStorage
*/
addTokenStorage () {
addTokenStorage : function () {
// ex.
// {
// "authenticator": "authenticator:oauth2",
@@ -291,19 +206,16 @@ class Service {
authenticated : this.token
});
localStorage.setItem("auth", data);
}
},
/**
* Reinitialise le token d'authentification du localStorage
*/
removeTokenStorage () {
removeTokenStorage : function () {
var data = JSON.stringify({
authenticated : {}
});
localStorage.setItem("auth", data);
}
};

// Mixin
Object.assign(Service.prototype, Users);

export default Service;
export default Connexion;
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ var Users = {
* @param {String} token - jeton d'authentification
* @returns {Promise} - ...
*/
getUserMe : (token) => {
getUserMe : function (token) {
var url = `https://data.geopf.fr/api/users/me`;
var settings = {
method : "GET",
Loading