Repository: auth0/auth0-spa-js
Pull request #220 (2019-09-19 04:15:53)

Add optional token issuer config
### Description

In some Auth0 distributions, especially those using the appliance, the `issuer` may be different from the custom domain.

This PR provides an option for specifying a separate issuer.

### Testing

Best approach to test is to provide an `issuer` referencing a domain different to the authorize domain.

### Checklist

- [x] I have added documentation for new/changed functionality in this PR or in auth0.com/docs
- [x] All active GitHub checks for tests, formatting, and security are passing
- [x] The correct base branch is being used, if not `master`


willhackett: Doneskies. Thanks @luisrudge 
luisrudge: @willhackett thank you for removing the html files 😅 Can you please add a test for this use case to make sure we don't break it in the future? `https://${this.options.issuer}/`
JiiB: This is exactly what I'm looking for. Any chance this PR gets merged soon? @willhackett @luisrudge  
stevehobbsdev: @JiiB Just waiting on @willhackett to provide the additional test case we've asked for, then we can look at merging.
willhackett: @luisrudge how many tests are you looking for? Can you please take a look at https://github.com/auth0/auth0-spa-js/pull/220/files#diff-6cd20e1bba7d6218e1b84e78e294bef6R313 and see if that's sufficient. Happy to add more.
luisrudge: @willhackett this one is perfect. thank you so much! 🎉 


Patch:
diff --git a/package-lock.json b/package-lock.json
index 8f5528d..756638a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "@auth0/auth0-spa-js",
-  "version": "1.2.2",
+  "version": "1.2.4",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/src/Auth0Client.ts b/src/Auth0Client.ts
index 4f94cbb..8717923 100644
--- a/src/Auth0Client.ts
+++ b/src/Auth0Client.ts
@@ -27,12 +27,16 @@ export default class Auth0Client {
   private cache: Cache;
   private transactionManager: TransactionManager;
   private domainUrl: string;
+  private tokenIssuer: string;
   private readonly DEFAULT_SCOPE = 'openid profile email';
 
   constructor(private options: Auth0ClientOptions) {
     this.cache = new Cache();
     this.transactionManager = new TransactionManager();
     this.domainUrl = `https://${this.options.domain}`;
+    this.tokenIssuer = this.options.issuer
+      ? `https://${this.options.issuer}/`
+      : `${this.domainUrl}/`;
   }
   private _url(path) {
     const telemetry = encodeURIComponent(
@@ -75,7 +79,7 @@ export default class Auth0Client {
   }
   private _verifyIdToken(id_token: string, nonce?: string) {
     return verifyIdToken({
-      iss: `${this.domainUrl}/`,
+      iss: this.tokenIssuer,
       aud: this.options.client_id,
       id_token,
       nonce,
diff --git a/src/global.ts b/src/global.ts
index 6360ac0..f2bc7a1 100644
--- a/src/global.ts
+++ b/src/global.ts
@@ -68,6 +68,10 @@ interface Auth0ClientOptions extends BaseLoginOptions {
    * (when using [custom domains](https://auth0.com/docs/custom-domains))
    */
   domain: string;
+  /**
+   * The issuer to be used for validation of JWTs, optionally defaults to the domain above
+   */
+  issuer?: string;
   /**
    * The Client ID found on your Application settings page
    */


Test patch:
diff --git a/__tests__/index.test.ts b/__tests__/index.test.ts
index 4e64584..7491ed3 100644
--- a/__tests__/index.test.ts
+++ b/__tests__/index.test.ts
@@ -310,6 +310,19 @@ describe('Auth0', () => {
         iss: 'https://test.auth0.com/'
       });
     });
+    it('calls `tokenVerifier.verify` with the `issuer` from in the oauth/token response', async () => {
+      const { auth0, tokenVerifier } = await setup({
+        issuer: 'test-123.auth0.com'
+      });
+
+      await auth0.loginWithPopup({});
+      expect(tokenVerifier).toHaveBeenCalledWith({
+        aud: 'test-client-id',
+        id_token: TEST_ID_TOKEN,
+        nonce: TEST_RANDOM_STRING,
+        iss: 'https://test-123.auth0.com/'
+      });
+    });
     it('calls `tokenVerifier.verify` with the `leeway` from constructor', async () => {
       const { auth0, tokenVerifier } = await setup({ leeway: 10 });