authts / oidc-client-ts

OpenID Connect (OIDC) and OAuth2 protocol support for browser-based JavaScript applications
https://authts.github.io/oidc-client-ts/
Apache License 2.0
1.42k stars 214 forks source link

Have an ergonomic way to do dynamic client registration #1027

Open sandhose opened 1 year ago

sandhose commented 1 year ago

There is no builtin way to do client registration as defined in OpenID Connect Dynamic Client Registration 1.0.

Currently, if one wanted to do a dynamic client registration, it would look like this:

const settings = new OidcClientSettingsStore({
    authority,
    redirect_uri,
    client_id: '', // Not known yet, but this is needed to make the type checker happy
});
const metadataService = new MetadataService(settings);
// Fetch the metadata and signing keys here, so that we can pass them in the OidcClient later and avoid loading twice
const metadata = await metadataService.getMetadata();
const signingKeys = (await metadataService.getSigningKeys()) ?? undefined;

// Check that there is a registration_endpoint advertised by the server
const registrationEndpoint = metadata['registration_endpoint'];
if (!registrationEndpoint) {
    throw new Error('Issuer does not support dynamic client registration');
}

// Do the client registration
const response = await fetch(registrationEndpoint, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({
        client_name: 'Some client name',
        client_uri: window.location.origin,
        contacts: ['a-contact@email'],
        application_type: 'web',
        redirect_uris: [redirect_uri],
        grant_types: ['authorization_code', 'refresh_token'],
        response_types: ['code'],
        token_endpoint_auth_method: 'none',
    }),
});
const registration = await response.json();

// Extract the returned client_id
const client_id = response.body['client_id'];
if (!client_id) {
    throw new Error('Invalid client ID');
}

// And construct an OidcClient with it
return new OidcClient({
    authority,
    client_id,
    scope: 'openid',
    redirect_uri,
    response_type: 'code',
    response_mode: 'fragment',
    signingKeys,
    metadata,
});

There should be a better, more ergonomic way to do, like a UnregisteredOidcClient, with a register method which would do a dynamic client registration and return an OidcClient

pamapa commented 1 year ago

You could write your code more elegant (like here https://github.com/authts/oidc-client-ts/issues/916#issuecomment-1567708223) by extending OidcClient. For the json request you could use the JsonService...

jpshaw45 commented 4 months ago

@pamapa, The solution in the comment is slightly differ from our need.

@sandhose I am also stuck with the same. Any luck!!

Please share some usage example. That will more helpful 😊