From 8c8eb9020a38eb9b3c65a071e293e96f0423e784 Mon Sep 17 00:00:00 2001 From: Jim Isaacs Date: Mon, 1 Mar 2021 17:32:44 -0800 Subject: [PATCH] some exports cleanup still a WIP to see if I can continue to attack circular architecture --- src/binding-post.ts | 8 +- src/binding-redirect.ts | 6 +- src/binding.ts | 16 ++++ src/entity-idp.ts | 28 +++++-- src/entity-sp.ts | 35 +++++++-- src/entity.ts | 79 +++++++++++++++----- src/flow.ts | 5 +- src/index.ts | 14 ++-- src/libsaml.ts | 82 ++++++++++---------- src/metadata-idp.ts | 14 +++- src/metadata-sp.ts | 21 ++++-- src/metadata.ts | 19 ++++- src/types.ts | 161 ---------------------------------------- src/urn.ts | 11 ++- test/issues.ts | 2 +- 15 files changed, 240 insertions(+), 261 deletions(-) create mode 100644 src/binding.ts delete mode 100644 src/types.ts diff --git a/src/binding-post.ts b/src/binding-post.ts index 8fa0ebe4..6d6b91f3 100644 --- a/src/binding-post.ts +++ b/src/binding-post.ts @@ -4,13 +4,13 @@ * @desc Binding-level API, declare the functions using POST binding */ -import type { BindingContext, Entity } from './entity'; -import type { IdentityProvider } from './entity-idp'; +import type { BindingContext } from './binding'; +import type { Entity, ParsedLogoutRequest } from './entity'; +import type { IdentityProvider, ParsedLoginRequest } from './entity-idp'; import type { ServiceProvider } from './entity-sp'; import { SamlifyError, SamlifyErrorCode } from './error'; import type { FlowResult } from './flow'; -import libsaml, { CustomTagReplacement } from './libsaml'; -import type { ParsedLoginRequest, ParsedLogoutRequest } from './types'; +import { CustomTagReplacement, libsaml } from './libsaml'; import { BindingNamespace, StatusCode } from './urn'; import { base64Decode, base64Encode, isNonEmptyArray } from './utility'; diff --git a/src/binding-redirect.ts b/src/binding-redirect.ts index cdeaff40..70101f48 100644 --- a/src/binding-redirect.ts +++ b/src/binding-redirect.ts @@ -3,13 +3,13 @@ * @author tngan * @desc Binding-level API, declare the functions using Redirect binding */ -import type { BindingContext, Entity } from './entity'; +import type { BindingContext } from './binding'; +import type { Entity, ParsedLogoutRequest } from './entity'; import type { IdentityProvider } from './entity-idp'; import type { ServiceProvider } from './entity-sp'; import { SamlifyError, SamlifyErrorCode } from './error'; import type { FlowResult } from './flow'; -import libsaml, { CustomTagReplacement } from './libsaml'; -import type { ParsedLogoutRequest, RequestSignatureAlgorithm } from './types'; +import { CustomTagReplacement, libsaml, RequestSignatureAlgorithm } from './libsaml'; import { BindingNamespace, StatusCode, wording } from './urn'; import { base64Encode, deflateString } from './utility'; diff --git a/src/binding.ts b/src/binding.ts new file mode 100644 index 00000000..77cba33e --- /dev/null +++ b/src/binding.ts @@ -0,0 +1,16 @@ +export interface ESamlHttpRequest { + query?: any; + body?: any; + octetString?: string; +} + +export interface BindingContext { + context: string; + id: string; +} + +export interface PostBindingContext extends BindingContext { + relayState?: string; + entityEndpoint: string; + type: 'SAMLRequest' | 'SAMLResponse'; +} diff --git a/src/entity-idp.ts b/src/entity-idp.ts index 4c210395..48fc04de 100644 --- a/src/entity-idp.ts +++ b/src/entity-idp.ts @@ -3,20 +3,38 @@ * @author tngan * @desc Declares the actions taken by identity provider */ +import type { ESamlHttpRequest } from './binding'; import postBinding from './binding-post'; -import { Entity, ESamlHttpRequest } from './entity'; +import { Entity, EntitySettings } from './entity'; import type { ServiceProvider } from './entity-sp'; import { SamlifyError, SamlifyErrorCode } from './error'; import { flow, FlowResult } from './flow'; -import type { CustomTagReplacement } from './libsaml'; -import metadataIdp, { MetadataIdp } from './metadata-idp'; -import type { IdentityProviderSettings, ParsedLoginRequest } from './types'; +import type { CustomTagReplacement, LoginResponseTemplate } from './libsaml'; +import type { SSOService } from './metadata'; +import { metadataIdp, MetadataIdp } from './metadata-idp'; import { BindingNamespace, ParserType } from './urn'; +export interface IdentityProviderSettings extends EntitySettings { + /** template of login response */ + loginResponseTemplate?: LoginResponseTemplate; + + singleSignOnService?: SSOService[]; + wantAuthnRequestsSigned?: boolean; + wantLogoutRequestSignedResponseSigned?: boolean; +} + +export interface ParsedLoginRequest { + authnContextClassRef?: string; + issuer?: string; + nameIDPolicy?: { format?: string; allowCreate?: string }; + request?: { id?: string; issueInstant?: string; destination?: string; assertionConsumerServiceUrl?: string }; + signature?: string; +} + /** * Identity prvider can be configured using either metadata importing or idpSetting */ -export default function (props: IdentityProviderSettings) { +export function identityProvider(props: IdentityProviderSettings) { return new IdentityProvider(props); } diff --git a/src/entity-sp.ts b/src/entity-sp.ts index 6f6dad7d..70c83038 100644 --- a/src/entity-sp.ts +++ b/src/entity-sp.ts @@ -3,21 +3,46 @@ * @author tngan * @desc Declares the actions taken by service provider */ +import type { BindingContext, ESamlHttpRequest, PostBindingContext } from './binding'; import postBinding from './binding-post'; import redirectBinding from './binding-redirect'; -import { BindingContext, Entity, ESamlHttpRequest, PostBindingContext } from './entity'; +import { Entity, EntitySettings } from './entity'; import type { IdentityProvider } from './entity-idp'; import { SamlifyError, SamlifyErrorCode } from './error'; import { flow, FlowResult } from './flow'; -import type { CustomTagReplacement } from './libsaml'; -import metadataSp, { MetadataSp } from './metadata-sp'; -import type { ParsedLoginResponse, ServiceProviderSettings } from './types'; +import type { CustomTagReplacement, SAMLDocumentTemplate } from './libsaml'; +import type { SSOService } from './metadata'; +import { metadataSp, MetadataSp } from './metadata-sp'; import { BindingNamespace, ParserType } from './urn'; +export interface ServiceProviderSettings extends EntitySettings { + authnRequestsSigned?: boolean; + wantAssertionsSigned?: boolean; + wantMessageSigned?: boolean; + assertionConsumerService?: SSOService[]; + + /** template of login request */ + loginRequestTemplate?: SAMLDocumentTemplate; + + allowCreate?: boolean; + // will be deprecated soon + relayState?: string; +} + +export interface ParsedLoginResponse { + attributes?: Record; + audience?: string; + conditions?: { notBefore: string; notOnOrAfter: string }; + issuer?: string; + nameID?: string; + response?: { id?: string; issueInstant?: string; destination?: string; inResponseTo?: string }; + sessionIndex?: { authnInstant?: string; sessionNotOnOrAfter?: string; sessionIndex?: string }; +} + /* * @desc interface function */ -export default function (props: ServiceProviderSettings) { +export function serviceProvider(props: ServiceProviderSettings) { return new ServiceProvider(props); } diff --git a/src/entity.ts b/src/entity.ts index 0efe925f..3abf2355 100644 --- a/src/entity.ts +++ b/src/entity.ts @@ -4,14 +4,22 @@ * @desc An abstraction for identity provider and service provider. */ import { v4 as uuid } from 'uuid'; +import type { BindingContext, ESamlHttpRequest, PostBindingContext } from './binding'; import postBinding from './binding-post'; import redirectBinding from './binding-redirect'; import { SamlifyError, SamlifyErrorCode } from './error'; import { flow, FlowResult } from './flow'; -import type { CustomTagReplacement } from './libsaml'; -import type { Metadata } from './metadata'; -import type { EntitySettings, ParsedLogoutRequest, ParsedLogoutResponse } from './types'; -import { algorithms, BindingNamespace, messageConfigurations, ParserType } from './urn'; +import type { + CustomTagReplacement, + EncryptionAlgorithm, + KeyEncryptionAlgorithm, + LogoutResponseTemplate, + RequestSignatureAlgorithm, + SAMLDocumentTemplate, + SignatureConfig, +} from './libsaml'; +import type { Metadata, SSOService } from './metadata'; +import { algorithms, BindingNamespace, messageConfigurations, MessageSignatureOrder, ParserType } from './urn'; import { isNonEmptyArray, isString } from './utility'; const dataEncryptionAlgorithm = algorithms.encryption.data; @@ -32,27 +40,58 @@ const defaultEntitySetting = { relayState: '', } as const; -export interface ESamlHttpRequest { - query?: any; - body?: any; - octetString?: string; -} +export interface EntitySettings { + metadata?: string | Buffer; + entityID?: string; + singleLogoutService?: SSOService[]; + + isAssertionEncrypted?: boolean; + + /** signature algorithm */ + requestSignatureAlgorithm?: RequestSignatureAlgorithm; + dataEncryptionAlgorithm?: EncryptionAlgorithm; + keyEncryptionAlgorithm?: KeyEncryptionAlgorithm; + + messageSigningOrder?: MessageSignatureOrder; + signatureConfig?: SignatureConfig; + transformationAlgorithms?: string[]; + wantLogoutRequestSigned?: boolean; + wantLogoutResponseSigned?: boolean; + + signingCert?: string | Buffer; + privateKey?: string | Buffer; + privateKeyPass?: string; + + encryptCert?: string | Buffer; + encPrivateKey?: string | Buffer; + encPrivateKeyPass?: string; + + /** template of logout request */ + logoutRequestTemplate?: SAMLDocumentTemplate; + /** template of logout response */ + logoutResponseTemplate?: LogoutResponseTemplate; + + nameIDFormat?: string[]; + // https://github.com/tngan/samlify/issues/337 + clockDrifts?: [number, number]; + /** customized function used for generating request ID */ + generateID?: () => string; -export interface BindingContext { - context: string; - id: string; + /** Declare the tag of specific xml document node. `TagPrefixKey` currently supports `encryptedAssertion` only */ + tagPrefix?: { encryptedAssertion?: string }; } -export interface PostBindingContext extends BindingContext { - relayState?: string; - entityEndpoint: string; - type: 'SAMLRequest' | 'SAMLResponse'; +export interface ParsedLogoutRequest { + request?: { id?: string; issueInstant?: string; destination?: string }; + issuer?: string; + nameID?: string; + signature?: string; } -export interface ParseResult { - samlContent: string; - extract: any; - sigAlg: string; +export interface ParsedLogoutResponse { + response?: { id?: string; destination?: string; inResponseTo?: string }; + issuer?: string; + signature?: string; } export class Entity { diff --git a/src/flow.ts b/src/flow.ts index 97b33553..3aac8cd8 100644 --- a/src/flow.ts +++ b/src/flow.ts @@ -1,4 +1,5 @@ -import type { Entity, ESamlHttpRequest } from './entity'; +import type { ESamlHttpRequest } from './binding'; +import type { Entity } from './entity'; import { SamlifyError, SamlifyErrorCode } from './error'; import { extract, @@ -10,7 +11,7 @@ import { logoutResponseFields, logoutResponseStatusFields, } from './extractor'; -import libsaml from './libsaml'; +import { libsaml } from './libsaml'; import { BindingNamespace, MessageSignatureOrder, ParserType, StatusCode, wording } from './urn'; import { base64Decode, inflateString } from './utility'; import { verifyTime } from './validator'; diff --git a/src/index.ts b/src/index.ts index 63d2725e..60f7a048 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,10 +1,8 @@ export * from './api'; -export { default as identityProvider } from './entity-idp'; -export { default as serviceProvider } from './entity-sp'; -export * as extractor from './extractor'; -export { default as libsaml } from './libsaml'; -export { default as metadataIdp } from './metadata-idp'; -export { default as metadataSp } from './metadata-sp'; -export * from './types'; +export * from './entity-idp'; +export * from './entity-sp'; +export * from './error'; +export * from './libsaml'; +export * from './metadata-idp'; +export * from './metadata-sp'; export * from './urn'; -export * as utility from './utility'; diff --git a/src/libsaml.ts b/src/libsaml.ts index c821d0ab..0145128a 100644 --- a/src/libsaml.ts +++ b/src/libsaml.ts @@ -5,7 +5,6 @@ */ import camelCase from 'camelcase'; -import type NodeRSA from 'node-rsa'; import nrsa from 'node-rsa'; import { FileKeyInfo, SignedXml } from 'xml-crypto'; import xmlenc from 'xml-encryption'; @@ -16,7 +15,6 @@ import type { Entity } from './entity'; import { SamlifyError, SamlifyErrorCode } from './error'; import { extract, isNode } from './extractor'; import type { Metadata } from './metadata'; -import type { RequestSignatureAlgorithm, SAMLDocumentTemplate, SignatureConfig } from './types'; import { algorithms, names, wording } from './urn'; import { base64Encode, @@ -28,6 +26,41 @@ import { readPrivateKey, } from './utility'; +export type { EncryptionAlgorithm, KeyEncryptionAlgorithm } from 'xml-encryption'; + +export type RequestSignatureAlgorithm = + | 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' + | 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' + | 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'; + +export type SignatureConfig = Parameters[1]; + +export interface SAMLDocumentTemplate { + context?: string; +} +export interface LoginResponseAttribute { + name: string; + nameFormat: string; + valueXsiType: string; + valueTag: string; + valueXmlnsXs?: string; + valueXmlnsXsi?: string; +} +export interface LoginResponseTemplate extends Required { + attributes?: LoginResponseAttribute[]; +} +export type LoginRequestTemplate = Required; + +export type LogoutRequestTemplate = Required; + +export type LogoutResponseTemplate = Required; + +export interface CustomTagReplacement< + Values extends Record = Record +> { + (template: string, values: Values): readonly [template?: string, values?: Values]; +} + const signatureAlgorithms = algorithms.signature; const digestAlgorithms = algorithms.digest; const certUse = wording.certUse; @@ -46,7 +79,7 @@ const dom = DOMParser; // } // } -export interface SignatureConstructor { +interface SignatureConstructor { rawSamlMessage: string; referenceTagXPath?: string; privateKey: string; @@ -59,49 +92,18 @@ export interface SignatureConstructor { transformationAlgorithms?: string[]; } -export interface SignatureVerifierOptions { +interface SignatureVerifierOptions { metadata?: Metadata; keyFile?: string; signatureAlgorithm?: RequestSignatureAlgorithm; } -export interface ExtractorResult { - [key: string]: any; - signature?: string | string[]; - issuer?: string | string[]; - nameid?: string; - notexist?: boolean; -} - -export interface LoginResponseAttribute { - name: string; - nameFormat: string; - valueXsiType: string; - valueTag: string; - valueXmlnsXs?: string; - valueXmlnsXsi?: string; -} -export interface LoginResponseTemplate extends Required { - attributes?: LoginResponseAttribute[]; -} -export type LoginRequestTemplate = Required; - -export type LogoutRequestTemplate = Required; - -export type LogoutResponseTemplate = Required; - -export type KeyUse = 'signing' | 'encryption'; +type KeyUse = 'signing' | 'encryption'; -export interface KeyComponent { +interface KeyComponent { [key: string]: any; } -export interface CustomTagReplacement< - Values extends Record = Record -> { - (template: string, values: Values): readonly [template?: string, values?: Values]; -} - const libSaml = () => { /** * @desc helper function to get back the query param for redirect binding for SLO/SSO @@ -166,7 +168,7 @@ const libSaml = () => { * @param {string} sigAlg signature algorithm * @return {string} signing algorithm short-hand for the module node-rsa */ - function getSigningScheme(sigAlg?: RequestSignatureAlgorithm): NodeRSA.Options['signingScheme'] { + function getSigningScheme(sigAlg?: RequestSignatureAlgorithm): nrsa.Options['signingScheme'] { if (sigAlg) { const algAlias = nrsaAliasMapping[sigAlg]; if (algAlias != null) return algAlias; @@ -529,7 +531,7 @@ const libSaml = () => { */ verifyMessageSignature( metadata: Metadata, - octetString: NodeRSA.Data, + octetString: nrsa.Data, signature: Buffer, verifyAlgorithm?: RequestSignatureAlgorithm ) { @@ -707,4 +709,4 @@ ${targetEntityMetadata.getX509Certificate(certUse.encrypt)} }; }; -export default libSaml(); +export const libsaml = libSaml(); diff --git a/src/metadata-idp.ts b/src/metadata-idp.ts index c14c33e8..229f6871 100644 --- a/src/metadata-idp.ts +++ b/src/metadata-idp.ts @@ -5,16 +5,22 @@ */ import xml from 'xml'; import { SamlifyError, SamlifyErrorCode } from './error'; -import libsaml from './libsaml'; -import { Metadata } from './metadata'; -import type { MetadataIdpConstructorOptions } from './types'; +import { libsaml, RequestSignatureAlgorithm } from './libsaml'; +import { Metadata, MetadataFile, MetadataOptions } from './metadata'; import { BindingNamespace, names } from './urn'; import { isNonEmptyArray, isString } from './utility'; +interface MetadataIdpOptions extends MetadataOptions { + requestSignatureAlgorithm?: RequestSignatureAlgorithm; + wantAuthnRequestsSigned?: boolean; +} + +export type MetadataIdpConstructorOptions = MetadataIdpOptions | MetadataFile; + /* * @desc interface function */ -export default function (meta: MetadataIdpConstructorOptions) { +export function metadataIdp(meta: MetadataIdpConstructorOptions) { return new MetadataIdp(meta); } diff --git a/src/metadata-sp.ts b/src/metadata-sp.ts index 687d3ba2..9f80176d 100644 --- a/src/metadata-sp.ts +++ b/src/metadata-sp.ts @@ -4,16 +4,27 @@ * @desc Metadata of service provider */ import xml from 'xml'; -import libsaml from './libsaml'; -import { Metadata } from './metadata'; -import type { MetadataSpConstructorOptions, MetaElement } from './types'; -import { BindingNamespace, elementsOrder as order, names } from './urn'; +import { libsaml } from './libsaml'; +import { Metadata, MetadataFile, MetadataOptions, SSOService } from './metadata'; +import { BindingNamespace, elementsOrder as order, MetaElement, names } from './urn'; import { isNonEmptyArray, isString } from './utility'; +interface MetadataSpOptions extends MetadataOptions { + assertionConsumerService?: SSOService[]; + authnRequestsSigned?: boolean; + elementsOrder?: (keyof MetaElement)[]; + // TODO: Not sure if this is used. Consider removing. + signatureConfig?: Record; + wantAssertionsSigned?: boolean; + wantMessageSigned?: boolean; +} + +export type MetadataSpConstructorOptions = MetadataSpOptions | MetadataFile; + /* * @desc interface function */ -export default function (meta: MetadataSpConstructorOptions) { +export function metadataSp(meta: MetadataSpConstructorOptions) { return new MetadataSp(meta); } diff --git a/src/metadata.ts b/src/metadata.ts index 5ba0df49..76a945fe 100644 --- a/src/metadata.ts +++ b/src/metadata.ts @@ -9,6 +9,23 @@ import { extract } from './extractor'; import type { BindingNamespace } from './urn'; import { isString } from './utility'; +export interface SSOService { + isDefault?: boolean; + Binding: BindingNamespace; + Location: string; +} + +export interface MetadataOptions { + encryptCert?: string | Buffer; + entityID?: string; + nameIDFormat?: string[]; + signingCert?: string | Buffer; + singleLogoutService?: SSOService[]; + singleSignOnService?: SSOService[]; +} + +export type MetadataFile = string | Buffer; + export class Metadata { private xmlString: string; protected meta: any; @@ -17,7 +34,7 @@ export class Metadata { * @param {string | Buffer} metadata xml * @param {object} extraParse for custom metadata extractor */ - constructor(xml: string | Buffer, extraParse: any = []) { + constructor(xml: MetadataFile, extraParse: any = []) { this.xmlString = xml.toString(); this.meta = extract( this.xmlString, diff --git a/src/types.ts b/src/types.ts deleted file mode 100644 index 5ed0ab36..00000000 --- a/src/types.ts +++ /dev/null @@ -1,161 +0,0 @@ -import type { SignedXml } from 'xml-crypto'; -import type { EncryptionAlgorithm, KeyEncryptionAlgorithm } from 'xml-encryption'; -import type { LoginResponseTemplate, LogoutResponseTemplate } from './libsaml'; -import type { BindingNamespace, MessageSignatureOrder } from './urn'; - -interface SSOService { - isDefault?: boolean; - Binding: BindingNamespace; - Location: string; -} - -export type RequestSignatureAlgorithm = - | 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' - | 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256' - | 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha512'; - -// https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf (P.16, 18) -export interface MetaElement { - AssertionConsumerService?: any[]; - AttributeConsumingService?: any[]; - KeyDescriptor?: any[]; - NameIDFormat?: any[]; - SingleLogoutService?: any[]; -} - -interface MetadataOptions { - encryptCert?: string | Buffer; - entityID?: string; - nameIDFormat?: string[]; - signingCert?: string | Buffer; - singleLogoutService?: SSOService[]; - singleSignOnService?: SSOService[]; -} - -interface MetadataIdpOptions extends MetadataOptions { - requestSignatureAlgorithm?: RequestSignatureAlgorithm; - wantAuthnRequestsSigned?: boolean; -} - -interface MetadataSpOptions extends MetadataOptions { - assertionConsumerService?: SSOService[]; - authnRequestsSigned?: boolean; - elementsOrder?: (keyof MetaElement)[]; - // TODO: Not sure if this is used. Consider removing. - signatureConfig?: Record; - wantAssertionsSigned?: boolean; - wantMessageSigned?: boolean; -} - -type MetadataFile = string | Buffer; - -export type MetadataIdpConstructorOptions = MetadataIdpOptions | MetadataFile; -export type MetadataSpConstructorOptions = MetadataSpOptions | MetadataFile; - -export interface SAMLDocumentTemplate { - context?: string; -} - -export type SignatureConfig = Parameters[1]; - -export interface EntitySettings { - metadata?: string | Buffer; - entityID?: string; - assertionConsumerService?: SSOService[]; - singleLogoutService?: SSOService[]; - - authnRequestsSigned?: boolean; - isAssertionEncrypted?: boolean; - - /** signature algorithm */ - requestSignatureAlgorithm?: RequestSignatureAlgorithm; - dataEncryptionAlgorithm?: EncryptionAlgorithm; - keyEncryptionAlgorithm?: KeyEncryptionAlgorithm; - - messageSigningOrder?: MessageSignatureOrder; - signatureConfig?: SignatureConfig; - transformationAlgorithms?: string[]; - wantAssertionsSigned?: boolean; - wantLogoutRequestSigned?: boolean; - wantLogoutResponseSigned?: boolean; - wantMessageSigned?: boolean; - - signingCert?: string | Buffer; - privateKey?: string | Buffer; - privateKeyPass?: string; - - encryptCert?: string | Buffer; - encPrivateKey?: string | Buffer; - encPrivateKeyPass?: string; - - /** template of login request */ - loginRequestTemplate?: SAMLDocumentTemplate; - /** template of logout request */ - logoutRequestTemplate?: SAMLDocumentTemplate; - /** template of logout response */ - logoutResponseTemplate?: LogoutResponseTemplate; - - nameIDFormat?: string[]; - allowCreate?: boolean; - // will be deprecated soon - relayState?: string; - // https://github.com/tngan/samlify/issues/337 - clockDrifts?: [number, number]; - /** customized function used for generating request ID */ - generateID?: () => string; - - /** Declare the tag of specific xml document node. `TagPrefixKey` currently supports `encryptedAssertion` only */ - tagPrefix?: { encryptedAssertion?: string }; -} - -export interface ServiceProviderSettings extends EntitySettings { - authnRequestsSigned?: boolean; - wantAssertionsSigned?: boolean; - wantMessageSigned?: boolean; - assertionConsumerService?: SSOService[]; - loginRequestTemplate?: SAMLDocumentTemplate; - logoutRequestTemplate?: SAMLDocumentTemplate; - transformationAlgorithms?: string[]; - allowCreate?: boolean; - // will be deprecated soon - relayState?: string; - // https://github.com/tngan/samlify/issues/337 - clockDrifts?: [number, number]; -} - -export interface IdentityProviderSettings extends EntitySettings { - /** template of login response */ - loginResponseTemplate?: LoginResponseTemplate; - - singleSignOnService?: SSOService[]; - wantAuthnRequestsSigned?: boolean; - wantLogoutRequestSignedResponseSigned?: boolean; -} - -export interface ParsedLoginRequest { - authnContextClassRef?: string; - issuer?: string; - nameIDPolicy?: { format?: string; allowCreate?: string }; - request?: { id?: string; issueInstant?: string; destination?: string; assertionConsumerServiceUrl?: string }; - signature?: string; -} -export interface ParsedLoginResponse { - attributes?: Record; - audience?: string; - conditions?: { notBefore: string; notOnOrAfter: string }; - issuer?: string; - nameID?: string; - response?: { id?: string; issueInstant?: string; destination?: string; inResponseTo?: string }; - sessionIndex?: { authnInstant?: string; sessionNotOnOrAfter?: string; sessionIndex?: string }; -} -export interface ParsedLogoutRequest { - request?: { id?: string; issueInstant?: string; destination?: string }; - issuer?: string; - nameID?: string; - signature?: string; -} -export interface ParsedLogoutResponse { - response?: { id?: string; destination?: string; inResponseTo?: string }; - issuer?: string; - signature?: string; -} diff --git a/src/urn.ts b/src/urn.ts index bff8a6e1..f9fe91c6 100644 --- a/src/urn.ts +++ b/src/urn.ts @@ -3,8 +3,6 @@ * @author tngan * @desc Includes all keywords need in samlify */ -import type { MetaElement } from './types'; - export enum BindingNamespace { Redirect = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect', Post = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST', @@ -162,6 +160,15 @@ export const wording = { }, } as const; +// https://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf (P.16, 18) +export interface MetaElement { + AssertionConsumerService?: any[]; + AttributeConsumingService?: any[]; + KeyDescriptor?: any[]; + NameIDFormat?: any[]; + SingleLogoutService?: any[]; +} + // https://wiki.shibboleth.net/confluence/display/CONCEPT/MetadataForSP // some idps restrict the order of elements in entity descriptors export const elementsOrder = { diff --git a/test/issues.ts b/test/issues.ts index 53b0fe82..5b3b63ff 100644 --- a/test/issues.ts +++ b/test/issues.ts @@ -6,7 +6,7 @@ import { DOMParser as dom } from 'xmldom'; import { identityProvider, serviceProvider } from '../src'; import { isSamlifyError, SamlifyErrorCode } from '../src/error'; import { extract, isElement } from '../src/extractor'; -import libsaml from '../src/libsaml'; +import { libsaml } from '../src/libsaml'; import { BindingNamespace, wording } from '../src/urn'; import { inflateString } from '../src/utility';