SSO between two angular applications

I have two angular applications with auth 0 authentication. I have a client applications in auth0 for each applications. Now I want to set Single sign on between these two applications. If user opens 1st application, he is authenticated and access token is generated and user is logged in. Now if user opens 2nd application, he should be logged in without redirecting to login page.
please advise how we can implement the sam,e

1 Like

Hi @meenu.bhatti,

Welcome to the Community!

This should work automatically. If you have the two applications configured, all the user has to do is click log in on the second application and they will automatically be logged in without having to provide credentials.

If this isn’t working for you then please describe how you have set things up, and what the behavior actually is.

Thanks,
Dan

Hi Dan,

Thanks for your response.

I have two applications configured in auth0 i.e they have two different clientIDs.
Requirement is if i log in into one application, opening other application should log in without redirecting to login page. We dont want user to click on login.

You could try running the same methods that clicking the login button does, when a user first visits the page.

my question is i am redirected to auth0 login page. We dont want this if user has already logged into another application with auth0 authentication opened in same browser

Yes, that should solve the issue. If you run loginWithRedirect (if you are using auth0-spa-js) then the user will be automatically logged in via a cookie.

This is not working for me. If i log out from one application, i am logged out from other application too. That is fine.
But after this if i log into first application, i am still redirected to auth0 login page for 2nd application.
First application has auth0-js and second has auth0-spa-js and second application should auto sign in

export class AuthService {

// Create an observable of Auth0 instance of client

auth0Client$ = (from(

createAuth0Client({

  domain: environment.auth0.domain,

  client_id: environment.auth0.clientID,

  redirect_uri: environment.auth0.redirectUri

})

) as Observable).pipe(

shareReplay(1), // Every subscription receives the same shared value

catchError(err => throwError(err))

);

private urlFromAuth: string;

// Define observables for SDK methods that return promises by default

// For each Auth0 SDK method, first ensure the client instance is ready

// concatMap: Using the client instance, call SDK method; SDK returns a promise

// from: Convert that resulting promise into an observable

isAuthenticated$ = this.auth0Client$.pipe(delay(500),

concatMap((client: Auth0Client) => from(client.isAuthenticated())),

tap(res => this.loggedIn = res)

);

handleRedirectCallback$ = this.auth0Client$.pipe(

concatMap((client: Auth0Client) => from(client.handleRedirectCallback(this.urlFromAuth)))

);

// Create subject and public observable of user profile data

private userProfileSubject$ = new BehaviorSubject(null);

userProfile$ = this.userProfileSubject$.asObservable();

// Create a local property for login status

loggedIn: boolean = null;

constructor(public auth: AuthService, public router: Router) {

// On initial load, check authentication state with authorization server

// Set up local auth streams if user is already authenticated

this.localAuthSetup();

// Handle redirect from Auth0 login

this.handleAuthCallback();

}

// When calling, options can be passed if desired

// https://auth0.github.io/auth0-spa-js/classes/auth0client.html#getuser

getUser$(options?): Observable {

return this.auth0Client$.pipe(

  concatMap((client: Auth0Client) => from(client.getUser(options))),

  tap(user => this.userProfileSubject$.next(user))

);

}

private localAuthSetup() {

// This should only be called on app initialization

// Set up local authentication streams

const checkAuth$ = this.isAuthenticated$.pipe(

  concatMap((loggedIn: boolean) => {

    if (loggedIn) {

      // If authenticated, get user and set in app

      // NOTE: you could pass options here if needed

      return this.getUser$();

    }

    // If not authenticated, return stream that emits 'false'

    return of(loggedIn);

  })

);

checkAuth$.subscribe();

}

login(redirectPath: string = ‘/’) {

// A desired redirect path can be passed to login method

// (e.g., from a route guard)

// Ensure Auth0 client instance exists

this.auth0Client$.subscribe((client: Auth0Client) => {

  // Call method to log in

  client.loginWithRedirect({

    redirect_uri: `${window.location.origin}`,

    appState: { target: redirectPath }

  });

});

}

private handleAuthCallback() {

// Call when app reloads after user logs in with Auth0

const params = window.location.search;

this.urlFromAuth = window.location.href;

if (params.includes('code=') && params.includes('state=')) {

  let targetRoute: string; // Path to redirect to after login processsed

  const authComplete$ = this.handleRedirectCallback$.pipe(

    // Have client, now call method to handle auth callback redirect

    tap(cbRes => {

      // Get and set target redirect route from callback results

      targetRoute = cbRes.appState && cbRes.appState.target ? cbRes.appState.target : '/';

    }),

    concatMap(() => {

      // Redirect callback complete; get user and login status

      return combineLatest([

        this.getUser$(),

        this.isAuthenticated$

      ]);

    })

  );

  // Subscribe to authentication completion observable

  // Response will be an array of user and login status

  authComplete$.subscribe(([user, loggedIn]) => {

    // Redirect to target route after callback processing

    this.router.navigate([targetRoute]);

  });

}

}

logout() {

// Ensure Auth0 client instance exists

this.auth0Client$.subscribe((client: Auth0Client) => {

  // Call method to log out

  client.logout({

    client_id: environment.auth0.clientID,

    returnTo: window.location.origin

  });

});

}

Can you send me a HAR of the transaction in a DM?

I ahve sent you the HAR file

1 Like

Great, I’ll review it now.