fix: documentation + moved discover into query

This commit is contained in:
Wyatt Johnson
2018-10-25 11:29:10 -06:00
parent eadf7bde43
commit ffd0f90965
8 changed files with 231 additions and 99 deletions
@@ -6,9 +6,9 @@ import { URL } from "url";
*/
export interface DiscoveryConfiguration {
issuer: string;
authorizationURL?: string;
authorizationURL: string;
tokenURL?: string;
jwksURI?: string;
jwksURI: string;
}
/**
@@ -18,9 +18,9 @@ export interface DiscoveryConfiguration {
*/
interface DiscoveryRawConfiguration {
issuer: string;
authorization_endpoint?: string;
authorization_endpoint: string;
token_endpoint?: string;
jwks_uri?: string;
jwks_uri: string;
}
/**
@@ -29,7 +29,9 @@ interface DiscoveryRawConfiguration {
* @param issuer the Issuer URL that should be used to determine the
* configuration
*/
export async function discover(issuer: URL): Promise<DiscoveryConfiguration> {
export async function discover(
issuer: URL
): Promise<DiscoveryConfiguration | null> {
// 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 =
@@ -38,13 +40,23 @@ export async function discover(issuer: URL): Promise<DiscoveryConfiguration> {
"/.well-known/openid-configuration";
const res = await fetch(configurationURL);
// Parse the configuration
const meta: DiscoveryRawConfiguration = await res.json();
// Ensure that it responds correctly.
if (res.status !== 200) {
return null;
}
return {
issuer: meta.issuer,
authorizationURL: meta.authorization_endpoint,
tokenURL: meta.token_endpoint,
jwksURI: meta.jwks_uri,
};
try {
// Parse the configuration
const meta: DiscoveryRawConfiguration = await res.json();
return {
issuer: meta.issuer,
authorizationURL: meta.authorization_endpoint,
tokenURL: meta.token_endpoint,
jwksURI: meta.jwks_uri,
};
} catch (err) {
// TODO: log the error
return null;
}
}
@@ -0,0 +1,14 @@
import DataLoader from "dataloader";
import TenantContext from "talk-server/graph/tenant/context";
import { GQLDiscoveredOIDCConfiguration } from "talk-server/graph/tenant/schema/__generated__/types";
import { discoverOIDCConfiguration } from "talk-server/services/tenant";
export default (ctx: TenantContext) => ({
discoverOIDCConfiguration: new DataLoader<
string,
GQLDiscoveredOIDCConfiguration | null
>(issuers =>
Promise.all(issuers.map(issuer => discoverOIDCConfiguration(issuer)))
),
});
@@ -1,9 +1,11 @@
import Context from "talk-server/graph/tenant/context";
import Assets from "./assets";
import Auth from "./auth";
import Comments from "./comments";
import Users from "./users";
export default (ctx: Context) => ({
Auth: Auth(ctx),
Assets: Assets(ctx),
Comments: Comments(ctx),
Users: Users(ctx),
@@ -4,8 +4,6 @@ import TenantContext from "talk-server/graph/tenant/context";
import {
GQLCreateOIDCAuthIntegrationInput,
GQLDeleteOIDCAuthIntegrationInput,
GQLDiscoverOIDCConfigurationInput,
GQLOIDCConfiguration,
GQLSettingsInput,
GQLUpdateOIDCAuthIntegrationInput,
} from "talk-server/graph/tenant/schema/__generated__/types";
@@ -13,7 +11,6 @@ import { Tenant } from "talk-server/models/tenant";
import {
createOIDCAuthIntegration,
deleteOIDCAuthIntegration,
discoverOIDCConfiguration,
regenerateSSOKey,
update,
updateOIDCAuthIntegration,
@@ -24,9 +21,6 @@ export default ({ mongo, redis, tenantCache, tenant }: TenantContext) => ({
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),
createOIDCAuthIntegration: (
input: GQLCreateOIDCAuthIntegrationInput
): Promise<Tenant | null> =>
@@ -51,10 +51,6 @@ 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,
}),
createOIDCAuthIntegration: async (source, { input }, ctx) => ({
settings: await ctx.mutators.Settings.createOIDCAuthIntegration(input),
clientMutationId: input.clientMutationId,
@@ -6,6 +6,8 @@ const Query: GQLQueryTypeResolver<void> = {
id ? ctx.loaders.Comments.comment.load(id) : null,
settings: (source, args, ctx) => ctx.tenant,
me: (source, args, ctx) => ctx.user,
discoverOIDCConfiguration: (source, { issuer }, ctx) =>
ctx.loaders.Auth.discoverOIDCConfiguration.load(issuer),
};
export default Query;
@@ -312,6 +312,47 @@ type SSOAuthIntegration {
## OIDCAuthIntegration
##########################
"""
DiscoveredOIDCConfiguration contains the discovered Provider Metadata as defined
in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
Discovery is not supported on all providers, and is described in the OpenID
Connect Discovery 1.0 incorporating errata set 1:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
"""
type DiscoveredOIDCConfiguration {
"""
issuer is defined as the `issuer` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
issuer: String!
"""
authorizationURL is defined as the `authorization_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
authorizationURL: String!
"""
tokenURL is defined as the `token_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
tokenURL: String
"""
jwksURI is defined as the `jwks_uri` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
jwksURI: String!
}
"""
OIDCAuthIntegration provides a way to store Open ID Connect credentials. This
will be used in the admin to provide staff logins for users.
@@ -335,7 +376,9 @@ type OIDCAuthIntegration {
targetFilter: AuthenticationTargetFilter
"""
name is the label assigned to reference the provider of the OIDC integration.
name is the label assigned to reference the provider of the OIDC integration,
and will be used in situations where the name of the provider needs to be
displayed, like the login button.
"""
name: String
@@ -346,11 +389,46 @@ type OIDCAuthIntegration {
"""
callbackURL: String!
"""
clientID is the Client Identifier as defined in:
https://tools.ietf.org/html/rfc6749#section-2.2
"""
clientID: String! @auth(roles: [ADMIN])
"""
clientSecret is the Client Secret as defined in:
https://tools.ietf.org/html/rfc6749#section-2.3.1
"""
clientSecret: String! @auth(roles: [ADMIN])
"""
authorizationURL is defined as the `authorization_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
authorizationURL: String! @auth(roles: [ADMIN])
"""
tokenURL is defined as the `token_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
tokenURL: String! @auth(roles: [ADMIN])
"""
jwksURI is defined as the `jwks_uri` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
jwksURI: String! @auth(roles: [ADMIN])
"""
issuer is defined as the `issuer` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
issuer: String! @auth(roles: [ADMIN])
"""
@@ -1200,7 +1278,8 @@ type Query {
asset(id: ID, url: String): Asset
"""
me is the current logged in User.
me is the current logged in User. If no user is currently logged in, it will
return null.
"""
me: User
@@ -1208,6 +1287,18 @@ type Query {
settings is the Settings for a given Tenant.
"""
settings: Settings!
"""
discoverOIDCConfiguration will discover the OpenID Connect configuration based
on the provided issuer. Discovery is not supported on all providers, and is
described in the OpenID Connect Discovery 1.0 incorporating errata set 1:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig
If the provider does not support discovery, the response will be null.
"""
discoverOIDCConfiguration(issuer: String!): DiscoveredOIDCConfiguration
@auth(roles: [ADMIN])
}
################################################################################
@@ -1365,34 +1456,6 @@ input SettingsSSOAuthIntegrationInput {
displayNameEnable: Boolean
}
# input SettingsOIDCAuthIntegrationInput {
# enabled: Boolean
# """
# targetFilter will restrict where the authentication integration should be
# displayed. If the value of targetFilter is null, then the authentication
# integration should be displayed in all targets.
# """
# targetFilter: SettingsAuthenticationTargetFilterInput
# """
# name is the label assigned to reference the provider of the OIDC integration.
# """
# name: String
# clientID: String
# clientSecret: String
# authorizationURL: String
# tokenURL: String
# jwksURI: String
# issuer: String
# """
# displayNameEnable when enabled, will allow Users to set and view their
# displayName's.
# """
# displayNameEnable: Boolean
# }
input SettingsGoogleAuthIntegrationInput {
enabled: Boolean
@@ -1915,53 +1978,58 @@ type RegenerateSSOKeyPayload {
clientMutationId: String!
}
##################
## discoverOIDCConfiguration
##################
input DiscoverOIDCConfigurationInput {
"""
"""
issuer: String!
"""
clientMutationId is required for Relay support.
"""
clientMutationId: String!
}
type OIDCConfiguration {
issuer: String!
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!
}
##################
# createOIDCAuthIntegration
##################
input CreateOIDCAuthIntegrationConfigurationInput {
"""
name is the label assigned to reference the provider of the OIDC integration,
and will be used in situations where the name of the provider needs to be
displayed, like the login button.
"""
name: String!
"""
clientID is the Client Identifier as defined in:
https://tools.ietf.org/html/rfc6749#section-2.2
"""
clientID: String!
"""
clientSecret is the Client Secret as defined in:
https://tools.ietf.org/html/rfc6749#section-2.3.1
"""
clientSecret: String!
"""
authorizationURL is defined as the `authorization_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
authorizationURL: String!
"""
tokenURL is defined as the `token_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
tokenURL: String!
"""
jwksURI is defined as the `jwks_uri` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
jwksURI: String!
"""
issuer is defined as the `issuer` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
issuer: String!
}
@@ -1994,13 +2062,65 @@ type CreateOIDCAuthIntegrationPayload {
##################
input UpdateOIDCAuthIntegrationConfigurationInput {
"""
enabled, when true, allows the integration to be enabled.
"""
enabled: Boolean
"""
targetFilter will restrict where the authentication integration should be
displayed. If the value of targetFilter is null, then the authentication
integration should be displayed in all targets.
"""
targetFilter: SettingsAuthenticationTargetFilterInput
"""
name is the label assigned to reference the provider of the OIDC integration,
and will be used in situations where the name of the provider needs to be
displayed, like the login button.
"""
name: String
"""
clientID is the Client Identifier as defined in:
https://tools.ietf.org/html/rfc6749#section-2.2
"""
clientID: String
"""
clientSecret is the Client Secret as defined in:
https://tools.ietf.org/html/rfc6749#section-2.3.1
"""
clientSecret: String
"""
authorizationURL is defined as the `authorization_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
authorizationURL: String
"""
tokenURL is defined as the `token_endpoint` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
tokenURL: String
"""
jwksURI is defined as the `jwks_uri` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
jwksURI: String
"""
issuer is defined as the `issuer` in:
https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
"""
issuer: String
}
@@ -2091,14 +2211,6 @@ type Mutation {
regenerateSSOKey(input: RegenerateSSOKeyInput!): RegenerateSSOKeyPayload
@auth(roles: [ADMIN])
"""
discoverOIDCConfiguration will discover the OpenID Connect configuration based
on the provided input.
"""
discoverOIDCConfiguration(
input: DiscoverOIDCConfigurationInput!
): DiscoverOIDCConfigurationPayload @auth(roles: [ADMIN])
"""
createOIDCAuthIntegration will create a OpenID Connect auth integration.
"""
+2 -2
View File
@@ -293,7 +293,7 @@ export async function updateTenantOIDCAuthIntegration(
// $set: dotize({
// "auth.integrations.oidc.$[oidc]": input,
// }),
// FIXME: replace with the above one once the types are updated.
// FIXME: uncomment when https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29986 gets merged
$set: dotize({
"auth.integrations.oidc.$[]": input,
}),
@@ -301,7 +301,7 @@ export async function updateTenantOIDCAuthIntegration(
{
// Add an ArrayFilter to only update one of the OpenID Connect
// integrations.
// arrayFilters: [{ "oidc.id": oidcID }], // FIXME: add back when we got the mongo fixes in place
// arrayFilters: [{ "oidc.id": oidcID }], // FIXME: uncomment when https://github.com/DefinitelyTyped/DefinitelyTyped/pull/29986 gets merged
// False to return the updated document instead of the original
// document.
returnOriginal: false,