Skip to content

Commit

Permalink
Added fix auth with GSuite
Browse files Browse the repository at this point in the history
  • Loading branch information
DmtrPn committed Jul 15, 2020
1 parent fb1bda0 commit 4487ed6
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 2 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ The code was originally based on Michael Bosworth's [express-saml](https://githu

Passport-SAML has been tested to work with Onelogin, Okta, Shibboleth, [SimpleSAMLphp](http://simplesamlphp.org/) based Identity Providers, and with [Active Directory Federation Services](http://en.wikipedia.org/wiki/Active_Directory_Federation_Services).

In this fork fixed bag when authorize with GSuite ([when one of my users if logged in with his/her personal account only](https://stackoverflow.com/questions/58223843/google-saml-sso-403-app-not-configured-for-user-error-when-signed-into-persona))

## Installation

$ npm install passport-saml
Expand Down Expand Up @@ -118,6 +120,11 @@ type Profile = {
* `signatureAlgorithm`: optionally set the signature algorithm for signing requests, valid values are 'sha1' (default), 'sha256', or 'sha512'
* `digestAlgorithm`: optionally set the digest algorithm used to provide a digest for the signed data object, valid values are 'sha1' (default), 'sha256', or 'sha512'
* `xmlSignatureTransforms`: optionally set an array of signature transforms to be used in HTTP-POST signatures. By default this is `[ 'http://www.w3.org/2000/09/xmldsig#enveloped-signature', 'http://www.w3.org/2001/10/xml-exc-c14n#' ]`

* **For auth with GSuite**
* `googleAuth`: if set true, at authorization redirect to google account choose page [to fix a bag when one of my users if logged in with his/her personal account only](https://stackoverflow.com/questions/58223843/google-saml-sso-403-app-not-configured-for-user-error-when-signed-into-persona)
* `googleAccountChooserUrl`: google account chooser page url. Default `https://accounts.google.com/AccountChooser`

* **Additional SAML behaviors**
* `additionalParams`: dictionary of additional query params to add to all requests; if an object with this key is passed to `authenticate`, the dictionary of additional query params will be appended to those present on the returned URL, overriding any specified by initialization options' additional parameters (`additionalParams`, `additionalAuthorizeParams`, and `additionalLogoutParams`)
* `additionalAuthorizeParams`: dictionary of additional query params to add to 'authorize' requests
Expand Down
109 changes: 109 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Type definitions for passport-saml 1.1
// Project: https://github.com/bergie/passport-saml
// Definitions by: Chris Barth <https://github.com/cjbarth>
// Damian Assennato <https://github.com/dassennato>
// Karol Samborski <https://github.com/ksamborski>
// Jose Colella <https://github.com/josecolella>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 3.0

import passport = require('passport');
import express = require('express');

export interface CacheItem {
createdAt: Date;
value: any;
}

export interface CacheProvider {
save(key: string | null, value: any, callback: (err: Error | null, cacheItem: CacheItem) => void | null): void;
get(key: string, callback: (err: Error | null, value: any) => void | null): void;
remove(key: string, callback: (err: Error | null, key: string) => void | null): void;
}

export type VerifiedCallback = (err: Error | null, user?: object, info?: object) => void;

export type VerifyWithRequest = (req: express.Request, profile: Profile, done: VerifiedCallback) => void;

export type VerifyWithoutRequest = (profile: Profile, done: VerifiedCallback) => void;

export class Strategy extends passport.Strategy {
constructor(config: SamlConfig, verify: VerifyWithRequest | VerifyWithoutRequest);
authenticate(req: express.Request, options: AuthenticateOptions | AuthorizeOptions): void;
logout(req: express.Request, callback: (err: Error | null, url?: string) => void): void;
generateServiceProviderMetadata(decryptionCert: string | null, signingCert?: string | null): string;
}

export type CertCallback = (callback: (err: Error | null, cert?: string | string[]) => void) => void;

export interface SamlConfig {
// Core
callbackUrl?: string;
path?: string;
protocol?: string;
host?: string;
entryPoint?: string;
issuer?: string;
privateCert?: string;
cert?: string | string[] | CertCallback;
decryptionPvk?: string;
signatureAlgorithm?: 'sha1' | 'sha256' | 'sha512';
googleAuth?: boolean;
googleAccountChooserUrl?: string;

// Additional SAML behaviors
additionalParams?: any;
additionalAuthorizeParams?: any;
identifierFormat?: string;
acceptedClockSkewMs?: number;
attributeConsumingServiceIndex?: string;
disableRequestedAuthnContext?: boolean;
authnContext?: string;
forceAuthn?: boolean;
skipRequestCompression?: boolean;
authnRequestBinding?: string;
RACComparison?: 'exact' | 'minimum' | 'maximum' | 'better';
providerName?: string;
passive?: boolean;
idpIssuer?: string;
audience?: string;

// InResponseTo Validation
validateInResponseTo?: boolean;
requestIdExpirationPeriodMs?: number;
cacheProvider?: CacheProvider;

// Passport
name?: string;
passReqToCallback?: boolean;

// Logout
logoutUrl?: string;
additionalLogoutParams?: any;
logoutCallbackUrl?: string;
}

export interface AuthenticateOptions extends passport.AuthenticateOptions {
additionalParams?: object;
}

export interface AuthorizeOptions extends AuthenticateOptions {
samlFallback?: string;
}

export type Profile = {
issuer?: string;
sessionIndex?: string;
nameID?: string;
nameIDFormat?: string;
nameQualifier?: string;
spNameQualifier?: string;
ID?: string;
mail?: string; // InCommon Attribute urn:oid:0.9.2342.19200300.100.1.3
email?: string; // `mail` if not present in the assertion
getAssertionXml(): string; // get the raw assertion XML
getAssertion(): object; // get the assertion XML parsed as a JavaScript object
getSamlResponseXml(): string; // get the raw SAML response XML
} & {
[attributeName: string]: unknown; // arbitrary `AttributeValue`s
};
19 changes: 18 additions & 1 deletion lib/passport-saml/saml.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ SAML.prototype.initialize = function (options) {
throw new Error('Invalid property: cert must not be empty');
}

if (!options.googleAccountChooserUrl) {
options.googleAccountChooserUrl = 'https://accounts.google.com/AccountChooser';
}

if (!options.path) {
options.path = '/saml/consume';
}
Expand Down Expand Up @@ -344,7 +348,20 @@ SAML.prototype.requestToUrl = function (request, response, operation, additional
// https://nodejs.org/api/url.html#url_url_format_urlobj
delete target.search;

callback(null, url.format(target));
if (operation === 'authorize' && this.options.googleAuth) {
var accountChooserUrl = url.parse(this.options.googleAccountChooserUrl, true);

const targetQuery = url.format({ query: target.query });
target.query = {};

accountChooserUrl.query = {
continue: `${url.format(target)}${targetQuery}`,
};

callback(null, url.format(accountChooserUrl));
} else {
callback(null, url.format(target));
}
};

if (this.options.skipRequestCompression) {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "passport-saml",
"version": "1.2.0",
"version": "1.3.3",
"license": "MIT",
"keywords": [
"saml",
Expand All @@ -26,6 +26,7 @@
"url": "https://github.com/bergie/passport-saml.git"
},
"main": "./lib/passport-saml",
"types": "index.d.ts",
"dependencies": {
"debug": "^3.1.0",
"passport-strategy": "*",
Expand Down

0 comments on commit 4487ed6

Please sign in to comment.