Fixed provider.

This commit is contained in:
SamTV12345 2024-03-24 14:18:58 +01:00
parent 7f3195774f
commit aa627761e8
4 changed files with 538 additions and 80 deletions

View file

@ -1,60 +1,51 @@
import {ArgsExpressType} from "../types/ArgsExpressType";
import Provider, {Configuration} from 'oidc-provider';
import {OIDCAdapter} from "./OIDCAdapter";
import Provider, {Account, Configuration} from 'oidc-provider';
import {generateKeyPair, exportJWK} from 'jose'
const configuration: Configuration = {
// refer to the documentation for other available configuration
clients: [{
grant_types: ["refresh_token", "authorization_code"],
client_id: 'foo',
client_secret: 'bar',
application_type: 'web',
redirect_uris: ['http://localhost:9001/test'],
}],
cookies: {
keys: ['some secret key', 'and also the old rotated away some time ago', 'and one more'],
},
claims: {
address: ['address'],
email: ['email', 'email_verified'],
phone: ['phone_number', 'phone_number_verified'],
profile: ['birthdate', 'family_name', 'gender', 'given_name', 'locale', 'middle_name', 'name',
'nickname', 'picture', 'preferred_username', 'profile', 'updated_at', 'website', 'zoneinfo'],
},
features: {
devInteractions: { enabled: false }, // defaults to true
deviceFlow: { enabled: true }, // defaults to false
revocation: { enabled: true }, // defaults to false
},
adapter: OIDCAdapter,
jwks: {
keys: [
{
d: 'VEZOsY07JTFzGTqv6cC2Y32vsfChind2I_TTuvV225_-0zrSej3XLRg8iE_u0-3GSgiGi4WImmTwmEgLo4Qp3uEcxCYbt4NMJC7fwT2i3dfRZjtZ4yJwFl0SIj8TgfQ8ptwZbFZUlcHGXZIr4nL8GXyQT0CK8wy4COfmymHrrUoyfZA154ql_OsoiupSUCRcKVvZj2JHL2KILsq_sh_l7g2dqAN8D7jYfJ58MkqlknBMa2-zi5I0-1JUOwztVNml_zGrp27UbEU60RqV3GHjoqwI6m01U7K0a8Q_SQAKYGqgepbAYOA-P4_TLl5KC4-WWBZu_rVfwgSENwWNEhw8oQ',
dp: 'E1Y-SN4bQqX7kP-bNgZ_gEv-pixJ5F_EGocHKfS56jtzRqQdTurrk4jIVpI-ZITA88lWAHxjD-OaoJUh9Jupd_lwD5Si80PyVxOMI2xaGQiF0lbKJfD38Sh8frRpgelZVaK_gm834B6SLfxKdNsP04DsJqGKktODF_fZeaGFPH0',
dq: 'F90JPxevQYOlAgEH0TUt1-3_hyxY6cfPRU2HQBaahyWrtCWpaOzenKZnvGFZdg-BuLVKjCchq3G_70OLE-XDP_ol0UTJmDTT-WyuJQdEMpt_WFF9yJGoeIu8yohfeLatU-67ukjghJ0s9CBzNE_LrGEV6Cup3FXywpSYZAV3iqc',
e: 'AQAB',
kty: 'RSA',
n: 'xwQ72P9z9OYshiQ-ntDYaPnnfwG6u9JAdLMZ5o0dmjlcyrvwQRdoFIKPnO65Q8mh6F_LDSxjxa2Yzo_wdjhbPZLjfUJXgCzm54cClXzT5twzo7lzoAfaJlkTsoZc2HFWqmcri0BuzmTFLZx2Q7wYBm0pXHmQKF0V-C1O6NWfd4mfBhbM-I1tHYSpAMgarSm22WDMDx-WWI7TEzy2QhaBVaENW9BKaKkJklocAZCxk18WhR0fckIGiWiSM5FcU1PY2jfGsTmX505Ub7P5Dz75Ygqrutd5tFrcqyPAtPTFDk8X1InxkkUwpP3nFU5o50DGhwQolGYKPGtQ-ZtmbOfcWQ',
p: '5wC6nY6Ev5FqcLPCqn9fC6R9KUuBej6NaAVOKW7GXiOJAq2WrileGKfMc9kIny20zW3uWkRLm-O-3Yzze1zFpxmqvsvCxZ5ERVZ6leiNXSu3tez71ZZwp0O9gys4knjrI-9w46l_vFuRtjL6XEeFfHEZFaNJpz-lcnb3w0okrbM',
q: '3I1qeEDslZFB8iNfpKAdWtz_Wzm6-jayT_V6aIvhvMj5mnU-Xpj75zLPQSGa9wunMlOoZW9w1wDO1FVuDhwzeOJaTm-Ds0MezeC4U6nVGyyDHb4CUA3ml2tzt4yLrqGYMT7XbADSvuWYADHw79OFjEi4T3s3tJymhaBvy1ulv8M',
qi: 'wSbXte9PcPtr788e713KHQ4waE26CzoXx-JNOgN0iqJMN6C4_XJEX-cSvCZDf4rh7xpXN6SGLVd5ibIyDJi7bbi5EQ5AXjazPbLBjRthcGXsIuZ3AtQyR0CEWNSdM7EyM5TRdyZQ9kftfz9nI03guW3iKKASETqX2vh0Z8XRjyU',
use: 'sig',
}, {
crv: 'P-256',
d: 'K9xfPv773dZR22TVUB80xouzdF7qCg5cWjPjkHyv7Ws',
kty: 'EC',
use: 'sig',
x: 'FWZ9rSkLt6Dx9E3pxLybhdM6xgR5obGsj5_pqmnz5J4',
y: '_n8G69C-A2Xl4xUW2lF0i8ZGZnk_KPYrhv4GbTGu5G4',
},
],
clients: [ {
client_id: 'oidc_client',
client_secret: 'a_different_secret',
grant_types: ['authorization_code'],
response_types: ['code'],
redirect_uris: ['http://localhost:3001/cb']
},
{
client_id: 'app',
client_secret: 'a_secret',
grant_types: ['client_credentials'],
redirect_uris: [],
response_types: []
}
],
scopes: ['openid', 'profile', 'email'],
//adapter: MemoryAdapter,
/*findAccount: async (ctx, id) => {
console.log(ctx, id)
return {
accountId: id,
claims: () => ({
sub: id,
})
} satisfies Account
},*/
};
export const expressCreateServer = (hookName:string, args:ArgsExpressType, cb:Function) => {
const oidc = new Provider('http://localhost:9001', configuration);
args.app.use("/oidc",oidc.callback());
export const expressCreateServer = async (hookName: string, args: ArgsExpressType, cb: Function) => {
const {privateKey} = await generateKeyPair('RS256');
const privateKeyJWK = await exportJWK(privateKey);
const oidc = new Provider('http://localhost:9001', {
...configuration, jwks: {
keys: [
privateKeyJWK
],
},
});
oidc.on('authorization.error', (ctx, error) => {
console.log('authorization.error', error);
})
args.app.use("/oidc", oidc.callback());
cb();
}

View file

@ -1,41 +1,109 @@
import {Account, Adapter, AdapterPayload} from "oidc-provider";
import {LRUCache} from 'lru-cache';
import {Adapter, AdapterPayload} from "oidc-provider";
export class OIDCAdapter implements Adapter {
private store: Map<string, Account> = new Map();
private logins: Map<string, Account> = new Map();
consume(id: string): Promise<void | undefined> {
console.log('consume', id)
return Promise.resolve(undefined);
const options = {
max: 500,
// for use with tracking overall storage size
maxSize: 5000,
// how long to live in ms
ttl: 1000 * 60 * 5,
// return stale items before removing from cache?
allowStale: false,
updateAgeOnGet: false,
updateAgeOnHas: false,
}
const epochTime = (date = Date.now()) => Math.floor(date / 1000);
const storage = new LRUCache<string,AdapterPayload|string[]|string>(options);
function grantKeyFor(id: string) {
return `grant:${id}`;
}
function userCodeKeyFor(userCode:string) {
return `userCode:${userCode}`;
}
class MemoryAdapter implements Adapter{
private readonly name: string;
constructor(name:string) {
this.name = name;
}
destroy(id: string): Promise<void | undefined> {
console.log('destroy', id)
return Promise.resolve(undefined);
key(id:string) {
return `${this.name}:${id}`;
}
destroy(id:string) {
const key = this.key(id);
const found = storage.get(key) as AdapterPayload;
const grantId = found && found.grantId;
storage.delete(key);
if (grantId) {
const grantKey = grantKeyFor(grantId);
(storage.get(grantKey) as string[])!.forEach(token => storage.delete(token));
storage.delete(grantKey);
}
return Promise.resolve();
}
consume(id: string) {
(storage.get(this.key(id)) as AdapterPayload)!.consumed = epochTime();
return Promise.resolve();
}
find(id: string): Promise<AdapterPayload | void | undefined> {
console.log('find', id)
return Promise.resolve(undefined);
return Promise.resolve<AdapterPayload>(storage.get(this.key(id)) as AdapterPayload);
}
findByUserCode(userCode: string) {
const id = storage.get(userCodeKeyFor(userCode)) as string;
return this.find(id);
}
upsert(id: string, payload: any, expiresIn: number) {
console.log('upsert');
const key = this.key(id);
const { grantId, userCode } = payload;
if (grantId) {
const grantKey = grantKeyFor(grantId);
const grant = storage.get(grantKey) as unknown as string[];
if (!grant) {
storage.set(grantKey, [key]);
} else {
grant.push(key);
}
}
if (userCode) {
storage.set(userCodeKeyFor(userCode), id, {ttl:expiresIn * 1000});
}
storage.set(key, payload, {ttl: expiresIn * 1000});
return Promise.resolve();
}
findByUid(uid: string): Promise<AdapterPayload | void | undefined> {
console.log('findByUid', uid)
return Promise.resolve(undefined);
}
findByUserCode(userCode: string): Promise<AdapterPayload | void | undefined> {
console.log('findByUserCode', userCode)
console.log('findByUid', uid);
return Promise.resolve(undefined);
}
revokeByGrantId(grantId: string): Promise<void | undefined> {
console.log('revokeByGrantId', grantId)
console.log('findByUid', grantId);
return Promise.resolve(undefined);
}
upsert(id: string, payload: AdapterPayload, expiresIn: number): Promise<void | undefined> {
console.log('upsert', id, payload, expiresIn)
return Promise.resolve(undefined);
}
}
export default MemoryAdapter

View file

@ -45,6 +45,7 @@
"find-root": "1.1.0",
"formidable": "^3.5.1",
"http-errors": "^2.0.0",
"jose": "^5.2.3",
"js-cookie": "^3.0.5",
"jsdom": "^24.0.0",
"jsonminify": "0.4.2",
@ -95,6 +96,7 @@
"eslint": "^8.57.0",
"eslint-config-etherpad": "^4.0.4",
"etherpad-cli-client": "^3.0.2",
"lru-cache": "^10.2.0",
"mocha": "^10.3.0",
"mocha-froth": "^0.2.10",
"nodeify": "^1.0.1",