okta / okta-oidc-js

okta-oidc-js
https://github.com/okta/okta-oidc-js
Other
395 stars 232 forks source link

referrerPath not storing the correct value in session storage #786

Open baljinder-inmarsat opened 4 years ago

baljinder-inmarsat commented 4 years ago

When I load my portal with the following URL e.g. www.mywebsite.com/site1/page1 and then login into Okta. I get redirect back www.mywebsite.com/site1/implicit/callback. What happens then is when I land on my callback component and it handleAuthentication I get redirected back to www.mywebsite.com/page1. You would expect to be redirect to what you initial had in your address bar before logging in. I've been debugging it and noticed that, in this example, Site1 gets removed and stored without it in the sessionStorage 'referrerPath' . Also I have noticed When you are setting the FromUri you are using window.location.origin + fromUri. in this case is www.mywebsite.com + page1

Suggestion: Just store the pathname.

I'm submitting this issue for the package(s):

I'm submitting a:

Current behavior

  1. start portal with 'www.mywebsite.com/site1/page1'
  2. Get sent to okta login page and login
  3. get redirect to 'www.mywebsite.com/page1'

Expected behavior

    • start portal with 'www.mywebsite.com/site1/page1'
    • Get sent to okta login page and login
    • get redirect to 'www.mywebsite.com/site1/implicit/callback'
    • it hits handle authentication, does what it does. get sessionstorage value ' ''www.mywebsite.com/page1'. contextpath disappeared
    • Then redirects me to 'www.mywebsite.com/site1/page1'

Minimal reproduction of the problem with instructions

  1. start portal with 'www.mywebsite.com/site1/page1'
  2. Get sent to okta login page and login
  3. get redirect to 'www.mywebsite.com/site1/implicit/callback'
  4. it hits handle authentication, does what it does. get sessionstorage value ' ''www.mywebsite.com/site1/page1'.
  5. Then redirects me to '''www.mywebsite.com/page1'.

Extra information about the use case/user story you are trying to implement

Environment

mraible commented 4 years ago

If you change your redirectUri to contain "/site1", everything should work as expected. window.location.origin does not include the path.

baljinder-inmarsat commented 4 years ago

I cannot find of a way to do that on a initial login, I can as a logout feature. As far as I can tell the library handles that via the OktaAuthGuard. Unless you are referring the redirectUrl in the config but that needs to be set with 'implicit/callback'

mraible commented 4 years ago

@baljinder-inmarsat Yes, I'm referring to the redirectUri in the config. The whole purpose of it is to tell Okta where you want your app to come back to. The only reason we use window.location.origin in our examples is because it's dynamic so you won't need to change it for production. However, you will need to add the contextPath if your app has one.

baljinder-inmarsat commented 4 years ago

@mraible Sorry I think I didn't put the steps clearly enough, apologies. I get redirect back to my portal.

  1. start portal with 'www.mywebsite.com/site1/page1'
  2. Get sent to okta login page and login
  3. get redirect to 'www.mywebsite.com/site1/implicit/callback'
  4. it hits handle authentication, does what it does. get sessionstorage value ' ''www.mywebsite.com/page1'. contextpath disappeared
  5. Then redirects me to 'www.mywebsite.com/page1'
aarongranick-okta commented 4 years ago

@baljinder-inmarsat It seems you are serving your application with a base path of /site1. Do you have a <base href=> set in the document? I am also guessing that all routes are defined relative to the root,site1. Is this correct? Would you mind sharing your routing config? Specifically I am interested in how you are configuring angular so that it is aware of a root base url outside your application.

okta-angular is saving the URI here: https://github.com/okta/okta-oidc-js/blob/master/packages/okta-angular/src/okta/okta.guard.ts#L48

As a workaround, you could define an onAuthRequired function: https://github.com/okta/okta-oidc-js/tree/master/packages/okta-angular#okta_config here you can read the saved URI using getFromUri, convert it to an absolute URI and save it back using setFromUri

baljinder-inmarsat commented 4 years ago

Do you have a <base href=> set in the document? index.html - < base href="/" > angular.json (depends on which environment ) - "baseHref": "/site1/", "deployUrl": "/site1/",

Are the routes defined relative? Yes

Our Route Cong? I have slightly tweaked to minimize it, plus the path values are in a constant file. I have add comments beside them to give the value they have been set to:

export const routes: Routes = [
  // Error page ROUTE
  // Stays out so that we can hide header and menubar
  {
    path: ROUTES_CONSTANTS.ERROR,  // error/
    component: ErrorPageComponent,
    data: {
      title: 'ERRORS.TITLE'
    }
  },

  {
    path: '',
    component: LayoutComponent,
    canActivateChild: [InmOktaAuthGuardService, AuthGuardService], // TODO lets replace InmOktaAuthGuardService with OktaAuthGuard when they implement it
    children: [
      // APP ROUTES_CONSTANTS
      {
        path: ROUTES_CONSTANTS.DASHBOARD,  // we have a constant file, value is: ''
        loadChildren: () => import('./dashboard/dashboard.module').then(m => m.DashboardModule)
      },
  {
        path: ROUTES_CONSTANTS.ORDERS, // we have a constant file, value is: 'order'
        loadChildren: () => import('./orders/orders.module').then(m => m.OrdersModule),
        data: {
          access: [ xxx,yyy
          ]
        }
      }
      }
    ]
  },

  {
    path: '**',
    redirectTo: `/${ROUTES_CONSTANTS.NOT_FOUND}`
  }
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, {
      onSameUrlNavigation: 'reload',
      relativeLinkResolution: 'corrected',
      scrollPositionRestoration: 'top'
    })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule {}

As a workaround, you could define an onAuthRequired? will give it go. For me, the place to handle it is in the handle authentication. So my alternative is bit of hacky way. may give you an idea of whats seems to be going wrong for me:

 .handleAuthentication()
      .then(() => {

        const postLogoutUrl = environment.OKTA.postLogoutRedirectUri;  // e.g www.website.com/site1
        const siteDomain = `${window.location.origin}/`;  // e.g www.website.com
        let fromUri = okta.getFromUri(); // e,g www.website.com/orders , site1 disappeared
        const isCorrectPath = fromUri.includes(postLogoutUrl); // check if site1 is there, which is not on initial login
        fromUri = isCorrectPath ? fromUri : fromUri.replace(siteDomain, postLogoutUrl);

        window.location.replace(fromUri);
      })

@aarongranick-okta hope this helps, thanks for checking this out!

swiftone commented 4 years ago

Internal ref: OKTA-306430