import Provider from 'oidc-provider';
import { createOIDCRouter } from './router.js';
import { createIdentityServiceAdapterClass } from './adapter.js';
import { findUserById, loginUserBody, loginUserCredentials } from './user.js';
import { registerPasswordGrantType } from './password-grant.js';
export { createOIDCRouter } from './router.js';
export function createOIDC({ identitySrvClient, env, logger, config: { loginFn, post_logout_redirect_uris, localTokenServiceFactory, remoteTokenService, cookies, redirect_uris, client_id, client_secret, issuer, jwks, templates } }) {
    const adapterClass = createIdentityServiceAdapterClass(remoteTokenService ?? identitySrvClient.token, logger, localTokenServiceFactory);
    const provider = new Provider(issuer, {
        adapter: adapterClass,
        clients: [{
                post_logout_redirect_uris,
                client_id,
                client_secret,
                id_token_signed_response_alg: 'RS256',
                grant_types: ['refresh_token', 'authorization_code', 'password'],
                redirect_uris,
                scopes: ['openid', 'offline_access'],
                response_types: [
                    'code'
                ],
                token_endpoint_auth_method: 'client_secret_basic',
            }],
        // issueRefreshToken:  async (ctx, client, code) => {
        //   // Always issue refresh token
        //   return client.grantTypeAllowed('refresh_token');
        // },
        jwks,
        ttl: {
            Session: (1 * 24 * 60 * 60) * 1000
        },
        cookies: {
            long: { signed: false }, // 1 day in ms
            short: { signed: false },
            keys: cookies.keys,
        },
        // oidc-provider only looks up the accounts by their ID when it has to read the claims,
        // passing it our Account model method is sufficient, it should return a Promise that resolves
        // with an object with accountId property and a claims method.
        findAccount: async (ctx, id) => {
            try {
                const userService = ctx?.identitySrvClient?.user;
                return {
                    accountId: id,
                    claims: async (use, scope) => {
                        try {
                            const user = await findUserById(userService, id);
                            logger.debug('User found:', user);
                            return {
                                sub: id,
                                data: user
                            };
                        }
                        catch (error) {
                            const { code, message, stack } = error;
                            logger.error('OIDC findAccount claims error', { code, message, stack });
                            return {
                                sub: id,
                                data: {
                                    id,
                                }
                            };
                        }
                    },
                };
            }
            catch (error) {
                const { code, message, stack } = error;
                logger.error('OIDC findAccount error', { code, message, stack });
            }
        },
        claims: {
            acr: null,
            sid: null,
            auth_time: null,
            iss: null,
            openid: ['sub', 'data'],
        },
        responseTypes: [
            'code',
            'id_token',
            'id_token token',
            'code id_token',
            'code token',
            'code id_token token',
            'none',
        ],
        // let's tell oidc-provider where our own interactions will be
        // setting a nested route is just good practice so that users
        // don't run into weird issues with multiple interactions open
        // at a time.
        interactions: {
            url: (ctx) => `/interaction/${ctx.oidc.uid}`,
        },
        features: {
            introspection: {
                enabled: true
            },
            revocation: {
                enabled: true
            },
            devInteractions: {
                enabled: false // env === 'development'
            },
        },
        clientBasedCORS: () => true
    });
    // Disabled due to playground being disabled
    // provider.use(helmet());
    const router = createOIDCRouter({
        loginFn: loginFn ?? loginUserBody,
        templates,
        logger,
        provider,
        env,
    });
    registerPasswordGrantType({
        authLogService: identitySrvClient.authentication_log,
        authenticate: loginUserCredentials,
        provider
    }, logger);
    // Disable forbidding redirect to http/localhost in dev mode
    if (env === 'development') {
        const proto = provider.Client?.Schema?.prototype;
        if (proto) {
            const { invalidate: orig } = proto;
            proto.invalidate = function invalidate(message, code) {
                if (code === 'implicit-force-https' || code === 'implicit-forbid-localhost') {
                    return;
                }
                orig.call(this, message);
            };
        }
    }
    return {
        provider,
        router,
    };
}
//# sourceMappingURL=index.js.map