51 lines
2.4 KiB
JavaScript
51 lines
2.4 KiB
JavaScript
const urlJoin = require('url-join');
|
|
const CONFIG = require('../config/config');
|
|
|
|
// Serves the app actor at its canonical uri (`/as/actor/app`) with a Solid-OIDC dual
|
|
// personality, discriminated by the request's `JsonLdContext` header — same contract as
|
|
// the `/app` route (see app.service.js for the full story), but implemented as a
|
|
// standalone service with no dependency on the `app` service.
|
|
//
|
|
// WHY A SEPARATE SERVICE: the Solid-OIDC client_id IS the actor uri (the pod provider's
|
|
// auth-agent only returns the `Link: rel="interop:registeredAgent"` header when the
|
|
// requesting app's identity — the token's azp, i.e. this client_id — matches the
|
|
// registration's `registeredAgent`, which the pod stores under the actor uri). The
|
|
// adapter therefore fetches THIS path as the client metadata document. Routing the path
|
|
// to `app.get` deadlocked boot: `@activitypods/app`'s `awaitCreateComplete` polls the
|
|
// actor over HTTP while the `app` service is still starting, and an unregistered action
|
|
// 503s the poll it waits on. This service has no `started()` work and no dependencies,
|
|
// so it is routable long before the `app` service exists.
|
|
module.exports = {
|
|
name: 'client-id-doc',
|
|
actions: {
|
|
get: {
|
|
async handler(ctx) {
|
|
const req = ctx.params && ctx.params.$req;
|
|
const headers = (req && req.headers) || {};
|
|
const jsonLdContextKey = Object.keys(headers).find(key => key.toLowerCase() === 'jsonldcontext');
|
|
const isOidcClientIdDocument =
|
|
jsonLdContextKey !== undefined && String(headers[jsonLdContextKey]).includes('solid/oidc-context.jsonld');
|
|
|
|
if (isOidcClientIdDocument) {
|
|
// The client_id must equal the fetched URI exactly. `req.url` is rewritten to
|
|
// the alias remainder by moleculer-web; the raw path survives in `originalUrl`.
|
|
const requestPath = String((req && (req.originalUrl || req.url)) || '/as/actor/app').split('?')[0];
|
|
return {
|
|
'@context': ['https://www.w3.org/ns/solid/oidc-context.jsonld'],
|
|
client_id: urlJoin(CONFIG.HOME_URL, requestPath),
|
|
redirect_uris: [urlJoin(CONFIG.FRONT_URL, 'login')],
|
|
client_name: CONFIG.APP_NAME,
|
|
client_uri: CONFIG.FRONT_URL
|
|
};
|
|
}
|
|
|
|
return await ctx.call('ldp.resource.get', {
|
|
resourceUri: urlJoin(CONFIG.HOME_URL, 'as/actor/app'),
|
|
accept: 'application/ld+json',
|
|
webId: 'system'
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|