Skip to content

Passing options from a parent plugin loses the type inference for the ouath2 object #2

@alexkahndev

Description

@alexkahndev

I am trying to write a library around the plugin to add routes and functionality for a full auth flow with all of the providers. The issue arises from the fact that the user needs to be able to pass the options from the parent plugin to the oauth2 plugin. The type inference that is gained by having the oauth2 object with its specific providers is lost when it is passed as a parameter. The code for the auth wrapper functions as intended however it causes type errors and the type inference of knowing what providers are available is lost. When making a regular auth plugin using a predefined provider like Google works as intended, the issue is you would have to make 48 of those and then keep them updated. The point of my auth library would be to allow any provider listed by the user and give them the routes and functionality for auth.

I created a sample repository to show the problem I'm describing https://github.com/alexkahndev/oauth2-type-example it has two files of note the auth-plugin and google-plugin.

The google-plugin is the individual specified provider and has type safety. In this scenario both Google and GitHub were listed as providers to the oauth2, so it knew what was available for authorize()

oauth2({
	Google: [
	        process.env.GOOGLE_CLIENT_ID,
	        process.env.GOOGLE_CLIENT_SECRET,
	        process.env.GOOGLE_REDIRECT_URI
        ],
        GitHub: ["client_id", "client_secret", "redirect_uri"]
})
const token = await oauth2.authorize("Google");

(property) authorize: <"Google">(provider: "Google") => Promise<OAuth2Tokens>
const token = await oauth2.authorize();

(property) authorize: <"GitHub" | "Google">(provider: "GitHub" | "Google", ...options: never) => Promise<OAuth2Tokens>

The auth-plugin is where the options are taken as a parameter by the parent and passed to oauth2 plugin. This passing of the options object losses the type safety and inference.

export const authPlugin = <Options extends ElysiaOauth2Options>(
	options: Options
) => {
return new Elysia().use(oauth2(options)
}

Authorize still works but it loses inference

const token = await oauth2.authorize("Google");

property) authorize: <"Google">(provider: "Google") => Promise<OAuth2Tokens>
const token = await oauth2.authorize();

property) authorize: <keyof Options>(provider: keyof Options, ...options: GetProviderAuthorizeOptions<keyof Options>) => Promise<Awaited<ReturnType<InstanceType<typeof import("/home/alexkahn/webdev/oauth2-type-example/node_modules/arctic/dist/index")[keyof Options]>["validateAuthorizationCode"]>>>

Refresh and revoke work functionally but produce a type error

const tokens = await oauth2.refresh(
	"Google",
	userRefreshToken.value
);

Argument of type 'string' is not assignable to parameter of type 'Extract<keyof Options, { [K in keyof RefreshableProvidersMap<keyof Options>]: RefreshableProvidersMap<keyof Options>[K] extends never ? never : K; }[keyof Options]>'.ts(2345)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions