Commit eabebab5 authored by Alexandre's avatar Alexandre

Merge branch '14-solid-auth' into 'master'

Resolve "Replace sib-oidc with solid-auth"

Closes #14

See merge request !11
parents 447b35d0 fe9d824e
Pipeline #4502 passed with stage
in 58 seconds
......@@ -10,35 +10,54 @@
sib-test {
display: block;
}
pre{
white-space: normal;
word-wrap: break-word;
}
.bu-test{
border: 3px solid red;
}
.bu-test[data-src]{
border-color: green;
}
.bu-test:after{
content: '???';
}
.bu-test[data-src]:after{
color: green;
content: attr(data-src);
}
</style>
</head>
<body>
<div bind-user class="bu-test">user-id: </div>
<h1>sib-oidc</h1>
<button id="reset">clear storage and set new URL</button>
<button id="reload">reload</button>
<sib-test>
<sib-test bind-user>
<button id="login">Se connecter</button>
<button id="logout">Se déconnecter</button>
<button id="stat">Status (console)</button>
<div id="result"></div>
</sib-test>
<sib-auth>
<sib-auth-provider
data-authority="https://test-paris.happy-dev.fr/openid/"
data-authority="https://api.test-paris.happy-dev.fr/"
data-client_id="234528"
data-id="paris"
>
</sib-auth-provider>
<sib-auth-provider
data-authority="https://test-paris.happy-dev.fr/openid/"
data-authority="https://api.test-paris.happy-dev.fr/"
data-client_id="234528"
data-id="paris2"
>
</sib-auth-provider>
</sib-auth>
<script>
reset.onclick = () => {
window.sessionStorage.clear();
......@@ -49,11 +68,10 @@
</script>
<script type="module">
import { SIBBase } from 'https://unpkg.com/@startinblox/core@0.7';
import { SIBBase, store } from 'https://unpkg.com/@startinblox/core@0.7';
class TestComponent extends SIBBase {
async connectedCallback() {
stat.onclick = () => console.log(this.getStatus());
login.onclick = () => this.triggerLogin();
logout.onclick = () => this.triggerLogout();
......@@ -66,21 +84,22 @@
async triggerLogout() {
await this.logout();
}
async getStatus() {
return this.getUser();
}
update() {
const user = this.getUser();
if (user) {
result.innerHTML = `Bonjour ${user.profile.name} !`;
} else {
async update() {
let user = await this.getUser();
let idToken = await this.getUserIdToken();
if (!user) {
result.innerHTML = `Vous n'êtes pas connecté !`;
return;
}
user = await store.get(user);
console.log(user);
result.innerHTML = `Bonjour ${user.username} !<br>ID Token: <pre>${idToken}</pre>`;
}
empty(){}
populate(){}
}
customElements.define('sib-test', TestComponent);
</script>
</body>
</html>
</html>
\ No newline at end of file
......@@ -620,7 +620,8 @@
"core-js": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.2.tgz",
"integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g=="
"integrity": "sha512-NdBPF/RVwPW6jr0NCILuyN9RiqLo2b1mddWHkUL+VnvcB7dzlnBJ1bXYntjpTGOgkZiiLWj2JxmOr7eGE3qK6g==",
"optional": true
},
"core-util-is": {
"version": "1.0.2",
......@@ -1391,7 +1392,8 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"aproba": {
"version": "1.2.0",
......@@ -1412,12 +1414,14 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
......@@ -1432,17 +1436,20 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"core-util-is": {
"version": "1.0.2",
......@@ -1559,7 +1566,8 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"ini": {
"version": "1.3.5",
......@@ -1571,6 +1579,7 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
......@@ -1585,6 +1594,7 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
......@@ -1592,12 +1602,14 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
......@@ -1616,6 +1628,7 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
......@@ -1696,7 +1709,8 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
......@@ -1708,6 +1722,7 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"wrappy": "1"
}
......@@ -1793,7 +1808,8 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"safer-buffer": {
"version": "2.1.2",
......@@ -1829,6 +1845,7 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
......@@ -1848,6 +1865,7 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
"optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
......@@ -1891,12 +1909,14 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
"dev": true,
"optional": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
"dev": true
"dev": true,
"optional": true
}
}
},
......
import 'https://unpkg.com/oidc-client@1.6';
Log.logger = console; // eslint-disable-line no-undef
Log.level = Log.INFO; // eslint-disable-line no-undef
const defaultSettings = {
redirect_uri: window.location.origin,
post_logout_redirect_uri: window.location.origin,
// authority: 'https://test-paris.happy-dev.fr/openid/',
// client_id: '833925',
response_type: 'id_token token',
scope: 'openid profile email',
automaticsilentrenew: 'true',
loaduserinfo: 'true',
};
import auth from 'https://dev.jspm.io/solid-auth-client';
class SIBAuthProvider extends HTMLElement {
/**
......@@ -24,7 +10,6 @@ class SIBAuthProvider extends HTMLElement {
constructor() {
super();
this.manager = null;
this.id = null;
}
......@@ -34,106 +19,20 @@ class SIBAuthProvider extends HTMLElement {
* with the params set in the component, render view
*/
async connectedCallback() {
const { authority, client_id, id } = this.dataset; // eslint-disable-line camelcase
const { id } = this.dataset; // eslint-disable-line camelcase
this.id = id;
const settings = Object.assign({}, defaultSettings, { authority, client_id });
this.manager = new UserManager(settings); // eslint-disable-line no-undef
this.render(this.dataset);
}
/** @function
* @name processState
* Try to get user, the if a state is set, call the appropriate method
* If failed, clear state
*/
async processState(parent) {
const user = await this.manager.getUser();
const state = parent.getState();
if (user) {
parent.setUser(user);
}
if (state && state.value) {
try {
switch (state.value) {
case 'login':
this.loginCallback(parent);
break;
case 'logout':
this.logoutCallback(parent);
break;
default:
parent.clearState();
}
} catch (e) {
parent.clearState();
}
}
}
/** @function
* @name disconnectedCallback
* Remove manager
*/
disconnectedCallback() {
this.manager = null;
}
/** @function
* @name login
* Start login procedure
* @param {SIBAuth} parent - SIBAuth parent instance
*/
async login(parent) {
const { token } = parent.setState('login', this.id);
await this.manager.signinRedirect({
state: token,
});
}
/** @function
* @name loginCallback
* Finish the login procedure
* @param {SIBAuth} parent - SIBAuth parent instance
*/
async loginCallback(parent) {
const { token, previousUri } = parent.getState();
const user = await this.manager.signinRedirectCallback();
if (user.state !== token) {
throw new Error('CRSF token doesnt match');
}
parent.setUser(user);
parent.clearState();
window.location.href = previousUri;
async login() {
auth.login(this.dataset.authority);
}
/** @function
* @name logout
* Start a logout procedure
* @param {SIBAuth} parent - SIBAuth parent instance
*/
async logout(parent) {
const { token } = parent.setState('logout', this.id);
await this.manager.signoutRedirect({
state: token,
});
}
/** @function
* @name logoutCallback
* Finish the logout procedure
* @param {SIBAuth} parent - SIBAuth parent instance
*/
async logoutCallback(parent) {
const { token } = parent.getState();
const signout = await this.manager.signoutRedirectCallback();
if (signout.state !== token) {
throw new Error('CRSF token doesnt match');
}
parent.setUser(null);
parent.clearState();
}
/** @function
* @name render
......
import 'https://unpkg.com/oidc-client@1.6';
import { SIBBase, Helpers } from 'https://unpkg.com/@startinblox/core@0.7';
import auth from 'https://dev.jspm.io/solid-auth-client';
import { Helpers, SIBBase } from 'https://unpkg.com/@startinblox/core@0.7';
const baseUrl = import.meta.url.replace(/\/[^/]*$/, '');
Helpers.importCSS(`${baseUrl}/sib-auth.css`);
......@@ -15,7 +15,7 @@ class SIBAuth extends HTMLElement {
constructor() {
super();
this.state = null;
this.provider = null;
this.user = null;
this.hide();
}
......@@ -27,8 +27,8 @@ class SIBAuth extends HTMLElement {
*/
async connectedCallback() {
this.install();
this.processState();
if (this.getUser()) {
// this.processState();
if (await this.getUserWebId()) {
this.dispatchUserInfo();
}
}
......@@ -38,8 +38,7 @@ class SIBAuth extends HTMLElement {
* Clear state and user, uninstall
*/
disconnectedCallback() {
this.setUser();
this.clearState();
auth.logout(); // .then(() => alert('Goodbye!'));
this.uninstall();
}
......@@ -51,7 +50,12 @@ class SIBAuth extends HTMLElement {
install() {
SIBBase.prototype.login = () => this.login();
SIBBase.prototype.logout = () => this.logout();
SIBBase.prototype.getUser = () => this.getUser();
SIBBase.prototype.getUserIdToken = () => this.getUserIdToken();
SIBBase.prototype.getUser = async () => {
const id = await this.getUserWebId();
if (!id) return null;
return { '@id': id };
};
this.bindUserObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes') {
......@@ -85,6 +89,7 @@ class SIBAuth extends HTMLElement {
SIBBase.prototype.login = null;
SIBBase.prototype.logout = null;
SIBBase.prototype.getUser = null;
SIBBase.prototype.getUserIdToken = null;
this.bindUserObserver.disconnect();
}
......@@ -134,57 +139,6 @@ class SIBAuth extends HTMLElement {
}
/** @function
* @name getState
* Search in localStorage for previous OIDC state
* @returns {State} - The state
*/
getState() {
if (!this.state) {
const state = localStorage.getItem('oidc_state');
if (state) {
this.state = JSON.parse(state);
} else {
this.state = {
provider: null,
value: null,
token: null,
previousUri: null,
};
}
}
return this.state;
}
/** @function
* @name setState
* Set state in localStorage
* @param {string} value - 'login' or 'logout', default null
* @param {string} provider - the id of the provider
* @returns {State} - The state
*/
setState(value = null, provider = null) {
const state = {
value,
provider,
token: (value === null) ? null : Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5),
previousUri: (value === null) ? null : window.location.href,
};
localStorage.setItem('oidc_state', JSON.stringify(state));
this.state = state;
return state;
}
/** @function
* @name clearState
* Reset current state
*/
clearState() {
this.setState();
}
/** @function
* @name processState
* Try to get user, the if a state is set, call the appropriate provider
......@@ -199,7 +153,8 @@ class SIBAuth extends HTMLElement {
/** @function
* @name dispatchUserInfo
* Try to replace data-src by user iri on [bind-user] elements
* @param {User} userWebId - User
* Try to replace data-src by userWebId iri on [bind-user] elements
*/
// eslint-disable-next-line class-methods-use-this
async dispatchUserInfo() {
......@@ -211,7 +166,7 @@ class SIBAuth extends HTMLElement {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', processDOM);
} else {
await processDOM();
processDOM();
}
}
......@@ -219,43 +174,46 @@ class SIBAuth extends HTMLElement {
* @name applyUser
* @param {Element} element
*/
applyUser(element) {
const user = this.getUser();
if (user == null) return;
const id = user.profile.website;
async applyUser(element) {
const id = await this.getUserWebId();
if (id == null) return;
if (element.getAttribute(id === 'data-src')) return;
element.setAttribute('data-src', id);
}
/** @function
* @name getUser
* @name getUserWebId
* Return User or undefined
* @return {User}
*/
getUser() {
if (this.user) {
return this.user;
}
const storedUser = localStorage.getItem('oidc_user');
if (!storedUser) {
return null;
}
this.user = JSON.parse(storedUser);
return this.user;
// eslint-disable-next-line class-methods-use-this
getUserWebId() {
return new Promise((resolve) => {
auth.trackSession((session) => {
if (!session) {
return resolve(null);
}
return resolve(session.webId);
});
});
}
/** @function
* @name setUser
* Set User
* @param {User} user
* @name getUserIdToken
* Return IdToken or undefined
* @return {User}
*/
setUser(user) {
localStorage.setItem('oidc_user', JSON.stringify(user));
this.user = user;
this.dispatchUserInfo();
// eslint-disable-next-line class-methods-use-this
getUserIdToken() {
return new Promise((resolve) => {
auth.trackSession((session) => {
if (!session) {
return resolve(null);
}
return resolve(session.authorization && session.authorization.id_token);
});
});
}
/** @function
......@@ -274,11 +232,8 @@ class SIBAuth extends HTMLElement {
* @name logout
* Try to logout if favorite provider is set
*/
async logout() {
const favoriteProvider = this.getFavoriteProvider();
if (favoriteProvider) {
this.callProvider(favoriteProvider, 'logout', this);
}
logout() {
auth.logout().then(() => this.dispatchUserInfo());
}
/** @function
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment