israx / hello-world

0 stars 0 forks source link

Amplify 6 logout issue with Single sign on #58

Closed israx closed 2 months ago

israx commented 2 months ago

Before opening, please confirm:

JavaScript Framework

Angular

Amplify APIs

Authentication, Storage

Amplify Version

v6

Amplify Categories

auth, storage

Backend

Other

Environment information

``` System: OS: Linux 5.15 Ubuntu 20.04.6 LTS (Focal Fossa) CPU: (8) x64 11th Gen Intel(R) Core(TM) i5-1135G7 @ 2.40GHz Memory: 8.94 GB / 15.36 GB Container: Yes Shell: 5.0.17 - /bin/bash Binaries: Node: 20.15.1 - ~/.nvm/versions/node/v20.15.1/bin/node npm: 10.7.0 - ~/.nvm/versions/node/v20.15.1/bin/npm Browsers: Chrome: 126.0.6478.182 npmPackages: @angular-devkit/build-angular: ^17.3.8 => 17.3.8 @angular/animations: ^17.3.11 => 17.3.12 @angular/cdk: ^17.3.10 => 17.3.10 @angular/cli: ~17.3.8 => 17.3.8 @angular/common: ^17.3.11 => 17.3.12 @angular/compiler: ^17.3.11 => 17.3.12 @angular/compiler-cli: ^17.3.11 => 17.3.12 @angular/core: ^17.3.11 => 17.3.12 @angular/forms: ^17.3.11 => 17.3.12 @angular/material: ^17.3.10 => 17.3.10 @angular/platform-browser: ^17.3.11 => 17.3.12 @angular/platform-browser-dynamic: ^17.3.11 => 17.3.12 @angular/router: ^17.3.11 => 17.3.12 @types/google.maps: ^3.51.0 => 3.55.11 @types/jasmine: ~4.3.0 => 4.3.6 aws-amplify: ^6.4.2 => 6.4.3 aws-amplify/adapter-core: undefined () aws-amplify/analytics: undefined () aws-amplify/analytics/kinesis: undefined () aws-amplify/analytics/kinesis-firehose: undefined () aws-amplify/analytics/personalize: undefined () aws-amplify/analytics/pinpoint: undefined () aws-amplify/api: undefined () aws-amplify/api/server: undefined () aws-amplify/auth: undefined () aws-amplify/auth/cognito: undefined () aws-amplify/auth/cognito/server: undefined () aws-amplify/auth/enable-oauth-listener: undefined () aws-amplify/auth/server: undefined () aws-amplify/data: undefined () aws-amplify/data/server: undefined () aws-amplify/datastore: undefined () aws-amplify/in-app-messaging: undefined () aws-amplify/in-app-messaging/pinpoint: undefined () aws-amplify/push-notifications: undefined () aws-amplify/push-notifications/pinpoint: undefined () aws-amplify/storage: undefined () aws-amplify/storage/s3: undefined () aws-amplify/storage/s3/server: undefined () aws-amplify/storage/server: undefined () aws-amplify/utils: undefined () buffer: ^4.9.2 => 4.9.2 (5.7.1) jasmine-core: ~4.5.0 => 4.5.0 karma: ~6.4.0 => 6.4.3 karma-chrome-launcher: ~3.1.0 => 3.1.1 karma-coverage: ~2.2.0 => 2.2.1 karma-coverage-coffee-example: 1.0.0 karma-jasmine: ~5.1.0 => 5.1.0 karma-jasmine-html-reporter: ~2.0.0 => 2.0.0 moment: ^2.29.4 => 2.30.1 rxjs: ~7.8.0 => 7.8.1 rxjs/ajax: undefined () rxjs/fetch: undefined () rxjs/operators: undefined () rxjs/testing: undefined () rxjs/webSocket: undefined () tslib: ^2.3.0 => 2.6.3 (2.6.2, 1.14.1) typescript: ~5.4.5 => 5.4.5 zone.js: ~0.14.7 => 0.14.8 ```

Describe the bug

I am using Angular version 17.3.12 and Amplify v6.4.2. Using hosted UI as login method. We are make use of the Single sign on since we have multiple angular applications. Also, using Cookie storage as the storage mechanism for the amplify library.

The scenario is, [Consider I have 2 applications named App1 & App2]

  1. Login from App1(Have a landing page which contain a button which redirect to the cognito hosted ui (login page)
  2. If the login is success, i am able to switch the applications, so i can go with App2.
  3. Both applications using our custom library(A header section) , that contain logout button
Case 1:
              If I try to logout from the App1, it will successfully logout, and redirect to landing page

Case 2:
              If I try to logout from App2, it WON'T LOGOUT and no action is happening.
              Note: Observed that cookie is cleared. But if we refresh the tab, it will redirect to the landing page. 
              But upon clicking the login button, it will directly enter to the application home page 
              without prompting the credentials.

Expected behavior

While using Single sign on with my applications having same domain, expected to completely logout from all the linked applications seamlessly.

Reproduction steps

  1. Enable single sign on for multiple applications; say App1, App2, etc..
  2. Login using one application; say App1
  3. Navigate to App2 [Use cookie storage to share the token and other auth informations]
  4. Try to logout from the App2.

Code Snippet


import { Hub } from "aws-amplify/utils";
import { getCurrentUser, signInWithRedirect } from "aws-amplify/auth";

// Constructor of the landing page
constructor(private router: Router,
    private zone: NgZone) {
    // Used for listening to login events
    Hub.listen("auth", ({ payload }) => {
      switch (payload.event) {
        case 'signedIn':
        case "signInWithRedirect":
          this.zone.run(() => this.router.navigate(['/app/home']));
          break;
        default:
          // handle sign in failure
          this.zone.run(() => this.router.navigate(['/login']));
          break;
      }
    });

    //currentAuthenticatedUser: when user comes to login page again
    getCurrentUser()
      .then(() => {
        this.router.navigate(['/app/home'], { replaceUrl: true });
      }).catch((err) => {
        this.router.navigate(['/login']);
      })

  }

// This function is triggered when clicking "Login"
onLoginClick() {
    signInWithRedirect();;
}

// This function is triggered when we click on Logout
logout(){
    signOut({ global: true })
      .then(data => {
        console.log(data)
  })
      .catch(err => {
        console.log(err)
        signOut();
      });
  }

Log output

``` // Put your logs below this line ```

aws-exports.js

import { environment } from "../src/environments/environment";
import { ResourcesConfig } from "aws-amplify";
const awsAmplifyConfig: ResourcesConfig = {
    Auth: {
        Cognito: {
            userPoolId: environment.cognitoUserPoolId,
            userPoolClientId: environment.cognitoAppClientId,
            signUpVerificationMethod: 'code',
            loginWith: {
                oauth: {
                    domain: environment.cognitoAuthDomain,
                    scopes: [
                        "phone",
                        "email",
                        "openid",
                        "profile",
                        "aws.cognito.signin.user.admin"
                    ],
                    redirectSignIn: ['https://app1.dev.mydomain.com/app/home'],
                    redirectSignOut: ['https://app1.dev.mydomain.com/login'],
                    responseType: 'code'
                }
            }
        }
    }
};

export default awsAmplifyConfig;

Manual configuration

import { Amplify } from 'aws-amplify';
import { CookieStorage } from 'aws-amplify/utils';
import { cognitoUserPoolsTokenProvider } from 'aws-amplify/auth/cognito';
import awsAmplifyConfig from './aws-exports';

Amplify.configure(awsAmplifyConfig);

cognitoUserPoolsTokenProvider.setKeyValueStorage(new CookieStorage(environment.cookieStorage));
environment.cookieStorage

cookieStorage: {
    // - Cookie domain (only required if cookieStorage is provided)
    domain: `.mydomain.com`,
    // (optional) - Cookie path
    path: '/',
    // (optional) - Cookie expiration in days
    expires: 1,
    // (optional) - See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
    sameSite: `strict` as const,

    // (optional) - Cookie secure flag
    // Either true or false, indicating if the cookie transmission requires a secure protocol (https).
    secure: true,
  },

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

israx commented 2 months ago

Based on the information provided, it appears that you're experiencing an issue with logging out from App2 in a single sign-on (SSO) setup using AWS Amplify v6 with Angular. The problem seems to be related to the logout process not being properly handled for App2. Here's a workaround to address this issue:

  1. Update your logout function to explicitly specify the redirectSignOut URL for each app. This ensures that the correct redirect URL is used regardless of which app initiates the logout process.

  2. Modify your logout function in both App1 and App2 to use the following code:

import { signOut } from 'aws-amplify/auth';

async function logout() {
  try {
    await signOut({
      global: true,
      oauth: {
        redirectSignOut: 'https://app1.dev.mydomain.com/login', // Update this URL for each app
      },
    });
  } catch (error) {
    console.error('Error signing out: ', error);
  }
}
  1. Ensure that the redirectSignOut URL matches the one specified in your Cognito User Pool App Client settings.

  2. Update your AWS Amplify configuration in both apps to include all possible redirectSignOut URLs:

const awsAmplifyConfig: ResourcesConfig = {
  Auth: {
    Cognito: {
      // ... other configurations
      loginWith: {
        oauth: {
          // ... other oauth configurations
          redirectSignOut: [
            'https://app1.dev.mydomain.com/login',
            'https://app2.dev.mydomain.com/login'
          ],
        }
      }
    }
  }
};
  1. Clear all cookies and local storage in your browser after making these changes.

This workaround should resolve the issue by ensuring that the logout process is handled consistently across both applications. The global: true option in the signOut function will attempt to sign out from all devices, and specifying the redirectSignOut URL explicitly in the logout function will override any issues with matching the current window URL.

If you continue to experience issues after implementing this workaround, please provide more detailed error logs or network request information during the logout process from App2.

israx commented 2 months ago

I was able to solve the issue. Thanks

israx commented 2 months ago

Thank you for raising this issue. If you have any questions or if this issue resurfaces, please don't hesitate to reopen it or create a new one.