mirror of
https://github.com/wassname/talk.git
synced 2026-07-17 11:33:39 +08:00
feat: added OIDC discovery
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
import fetch from "node-fetch";
|
||||
import { URL } from "url";
|
||||
|
||||
/**
|
||||
* Configuration that Talk is expecting.
|
||||
*/
|
||||
export interface DiscoveryConfiguration {
|
||||
authorizationURL?: string;
|
||||
tokenURL?: string;
|
||||
jwksURI?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Subset of configuration as defined in the set of Provider Metadata:
|
||||
*
|
||||
* https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
|
||||
*/
|
||||
interface DiscoveryRawConfiguration {
|
||||
authorization_endpoint?: string;
|
||||
token_endpoint?: string;
|
||||
jwks_uri?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* discover will discover the configuration for the issuer.
|
||||
*
|
||||
* @param issuer the Issuer URL that should be used to determine the
|
||||
* configuration
|
||||
*/
|
||||
export async function discover(issuer: URL): Promise<DiscoveryConfiguration> {
|
||||
// Any provider MUST provide a .well-known url that is JSON parsable based
|
||||
// on the issuer: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
|
||||
const configurationURL =
|
||||
issuer.origin +
|
||||
issuer.pathname.replace(/\/$/, "") +
|
||||
"/.well-known/openid-configuration";
|
||||
const res = await fetch(configurationURL);
|
||||
|
||||
// Parse the configuration
|
||||
const meta: DiscoveryRawConfiguration = await res.json();
|
||||
|
||||
return {
|
||||
authorizationURL: meta.authorization_endpoint,
|
||||
tokenURL: meta.token_endpoint,
|
||||
jwksURI: meta.jwks_uri,
|
||||
};
|
||||
}
|
||||
@@ -1,13 +1,24 @@
|
||||
import { isNull, omitBy } from "lodash";
|
||||
|
||||
import TenantContext from "talk-server/graph/tenant/context";
|
||||
import { GQLSettingsInput } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import {
|
||||
GQLDiscoverOIDCConfigurationInput,
|
||||
GQLOIDCConfiguration,
|
||||
GQLSettingsInput,
|
||||
} from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import { Tenant } from "talk-server/models/tenant";
|
||||
import { regenerateSSOKey, update } from "talk-server/services/tenant";
|
||||
import {
|
||||
discoverOIDCConfiguration,
|
||||
regenerateSSOKey,
|
||||
update,
|
||||
} from "talk-server/services/tenant";
|
||||
|
||||
export default ({ mongo, redis, tenantCache, tenant }: TenantContext) => ({
|
||||
update: (input: GQLSettingsInput): Promise<Tenant | null> =>
|
||||
update(mongo, redis, tenantCache, tenant, omitBy(input, isNull)),
|
||||
regenerateSSOKey: (): Promise<Tenant | null> =>
|
||||
regenerateSSOKey(mongo, redis, tenantCache, tenant),
|
||||
discoverOIDCConfiguration: (
|
||||
input: GQLDiscoverOIDCConfigurationInput
|
||||
): Promise<GQLOIDCConfiguration> => discoverOIDCConfiguration(input.issuer),
|
||||
});
|
||||
|
||||
@@ -51,6 +51,10 @@ const Mutation: GQLMutationTypeResolver<void> = {
|
||||
settings: await ctx.mutators.Settings.regenerateSSOKey(),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
discoverOIDCConfiguration: async (source, { input }, ctx) => ({
|
||||
configuration: await ctx.mutators.Settings.discoverOIDCConfiguration(input),
|
||||
clientMutationId: input.clientMutationId,
|
||||
}),
|
||||
};
|
||||
|
||||
export default Mutation;
|
||||
|
||||
@@ -1900,6 +1900,41 @@ type RegenerateSSOKeyPayload {
|
||||
clientMutationId: String!
|
||||
}
|
||||
|
||||
##################
|
||||
## discoverOIDCConfiguration
|
||||
##################
|
||||
|
||||
input DiscoverOIDCConfigurationInput {
|
||||
"""
|
||||
|
||||
"""
|
||||
issuer: String!
|
||||
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
}
|
||||
|
||||
type OIDCConfiguration {
|
||||
authorizationURL: String
|
||||
tokenURL: String
|
||||
jwksURI: String
|
||||
}
|
||||
|
||||
type DiscoverOIDCConfigurationPayload {
|
||||
"""
|
||||
configuration was the discovered configuration for the OpenID Connect server
|
||||
given the provided issuer.
|
||||
"""
|
||||
configuration: OIDCConfiguration
|
||||
|
||||
"""
|
||||
clientMutationId is required for Relay support.
|
||||
"""
|
||||
clientMutationId: String!
|
||||
}
|
||||
|
||||
##################
|
||||
## Mutation
|
||||
##################
|
||||
@@ -1929,6 +1964,10 @@ type Mutation {
|
||||
regenerateSSOKey(input: RegenerateSSOKeyInput!): RegenerateSSOKeyPayload
|
||||
@auth(roles: [ADMIN])
|
||||
|
||||
discoverOIDCConfiguration(
|
||||
input: DiscoverOIDCConfigurationInput!
|
||||
): DiscoverOIDCConfigurationPayload @auth(roles: [ADMIN])
|
||||
|
||||
"""
|
||||
createCommentReaction will create a Reaction authored by the current logged in
|
||||
User on a Comment.
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Redis } from "ioredis";
|
||||
import { Db } from "mongodb";
|
||||
import { URL } from "url";
|
||||
|
||||
import { GQLSettingsInput } from "talk-server/graph/tenant/schema/__generated__/types";
|
||||
import {
|
||||
@@ -10,6 +11,7 @@ import {
|
||||
updateTenant,
|
||||
} from "talk-server/models/tenant";
|
||||
|
||||
import { discover } from "talk-server/app/middleware/passport/strategies/oidc/discover";
|
||||
import logger from "talk-server/logger";
|
||||
import TenantCache from "./cache";
|
||||
|
||||
@@ -98,3 +100,19 @@ export async function regenerateSSOKey(
|
||||
|
||||
return updatedTenant;
|
||||
}
|
||||
|
||||
/**
|
||||
* discoverOIDCConfiguration will discover the OpenID Connect configuration as
|
||||
* is required by any OpenID Connect compatible service:
|
||||
*
|
||||
* https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
|
||||
*
|
||||
* @param issuerString the issuer that should be used as the discovery root.
|
||||
*/
|
||||
export async function discoverOIDCConfiguration(issuerString: string) {
|
||||
// Parse the issuer.
|
||||
const issuer = new URL(issuerString);
|
||||
|
||||
// Discover the configuration.
|
||||
return discover(issuer);
|
||||
}
|
||||
|
||||
Vendored
-16
@@ -1,16 +0,0 @@
|
||||
declare module "webfinger" {
|
||||
export interface WebfingerOptions {
|
||||
webfingerOnly?: boolean;
|
||||
}
|
||||
|
||||
export interface WebfingerCallback {
|
||||
(err: Error, jrd: { [key: string]: any }): void;
|
||||
}
|
||||
|
||||
export function webfinger(
|
||||
resource: string,
|
||||
res: string,
|
||||
options: WebfingerOptions,
|
||||
callback: WebfingerCallback
|
||||
): void;
|
||||
}
|
||||
Reference in New Issue
Block a user