feat: added OIDC discovery

This commit is contained in:
Wyatt Johnson
2018-10-23 15:27:23 -06:00
parent 3b6f3c9ea8
commit 0bb64f1d97
8 changed files with 121 additions and 18 deletions
@@ -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.
+18
View File
@@ -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);
}
-16
View File
@@ -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;
}