1

I am implementing identity server 4 with vue js in client side.

Currently, I have only the admin login in the application, with the password and username.

I do not have any public site from where the USER get redirected to login. I wanted the user get redirected to login page directly when they hit the application client URL.

Currently in the sample version of identity server 4 the user needs to hit the login button on the navbar and redirected to sign in.

I wanted to do in the following ways:

  1. Client Hit the URL. Check whether the user is authenticated or not.
  2. Redirect to Identity Server.
  3. Sign In with Username/Password
  4. Redirect to client portal after successful login.

I have very hard time to integrate this approach in vue js.

With my current implementation the application is always running in the loop and it is always redirected to sign in.

store.getters.isAuthenticated is never true and it always redirecting the application with SignIn.

I couldn't figure out whether i have missed something in my router.beforeEach or something in the implementation of oidc.

Routes:

export const routes = [
  {
    component: Full,
    path: "/",
    meta: {
      requiresAuth: true
    },
    children: [
      {
        path: "/dashboard",
        name: "Dahboard",
        component: DashboardView,
        meta: {
          requiresAuth: true
        }
      },
      {
        path: "/signin",
        component: Signin
      },
      {
        path: "/company",
        component: Company,
        meta: {
          requiresAuth: true
        }
      }
    ]
  }
];

import Vue from "vue";
import VueRouter from "vue-router";
import { routes } from "./routes";
import store from '../store'

Vue.use(VueRouter);

let router = new VueRouter({
  mode: "history",
  routes
});

export default router;
router.beforeEach((to, from, next) => {
  if (store.getters.isAuthenticated) {
    const notValid = ['/signin', '/signup']

    if (notValid.lastIndexOf(to.path) >= 0) {
      next({
        path: '/dashboard'
      })
    } else if (to.path === '/signout') {
      store.commit('removeAuthentication')
      next({
        path: '/'
      })
    } else {
      next()
    }
  } else if (to.matched.some(record => record.meta.requiresAuth)) {
    next({
      path: '/signin',
      query: {
        redirect: to.fullPath
      }
    })
  } else if (to.path === '/signout') {
    next({
      path: '/'
    })
  } else {
    next()
  }
})

SignIn Component:

import authService from './authService';

export default {
    name: 'Auth',
    mounted() {
        authService.login();
        authService.completeLogin();
    }
};

Config.js

export default {
    authority: "https://localhost:44350",
    client_id: "js",
    redirect_uri: `${domain}/signin`,
    response_type: "id_token token",
    scope:"openid profile api1",
    post_logout_redirect_uri : `${domain}`,
    silent_redirect_uri: `${domain}/silent.html`,
}

Login: this.userManager.signinRedirect()

completeLogin: this.userManager.signinRedirectCallback()

Silent.html:

new Oidc.UserManager().signinSilentCallback()
.catch(function (error) {
    console.error(error);
});
Rasik
  • 1,961
  • 3
  • 35
  • 72
  • You should probably tag you tag you question with `openid-connect` (The protocol Identity server implements) and `oidc-client` the library you use on the SPA side. – mode777 Apr 07 '18 at 18:29

1 Answers1

1

I'm not sure I understand everything correctly and I never worked with Vue. But let me describe a typical implicit flow which I assume, you want to achieve here:

  1. The user will hit your site unauthenticated (e.g. yoursite.com/dashboard)
  2. The AuthService will try to sign in the user - i.e. he/she will be redirected to the login page of identity server
  3. If the user does not have a valid session on identity server he/she will be promted for credentials. Otherwise he/she will be immediately redirected back to the requested redirect uri of your site (e.g. yoursite.com/signin).
  4. At this point the user is back at your site but still not logged in. You will notice that the url will contain a lot of additional text after the '#' character (e.g. yoursite.com/singin#access_token=ey456...)
  5. When you call completeLogin() oidc-client will read this data and save it (e.g. in your browsers session storage) - after this method completes, your user is logged in and you can redirect him/her to the original site (e.g. yoursite.com/dashboard)

You probably get an infinite loop between steps 1 - 4, because you never allow step 5 to happen, so the login never completes.

Try to change your signin component

import authService from './authService';

export default {
    name: 'Auth',
    mounted() {
        //authService.login(); -- This line will redirect the user again before the login can complete
        authService.completeLogin();
    }
};

Also make sure the signin component can be accessed by the user even if he/she is not yet authenticated, so he/she can complete the login process.

mode777
  • 3,037
  • 2
  • 23
  • 34
  • Yes you are right I am getting the looop with step 4. It is redirecting with same token url every time. The complete login never happen. So, where should I call 'signinRedirect()'? – Rasik Apr 08 '18 at 00:49
  • It depends on the use case. Call signInRedirect() whenever the user needs to be authenticated but is not yet. E.g. before loading a certain route or when the user clicks the login button. Don' call signinredirect before loading or inside the sigin component, as this will trigger a loop. – mode777 Apr 08 '18 at 06:49
  • Yes this same thing is happening in my application i am doing completely the way you saying not to do. But i am strucked to move that out of SignIn. Because i need to redirect my application to SignIn component after checking whether the route is authenticated or not. and it is moving in the loop, because the completeLogin() is never completed. – Rasik Apr 08 '18 at 07:00
  • Ok here's you error: The signin components should be accessed **after** the user was logged in. You have to set up your routing so that the identity server can redirect ot it e.g. `http://yoursite.com/signin` and it has to be freely accesable without being logged in. You don't need a signin component before login, because you can just call `signInRedirect()` when the user should log in. – mode777 Apr 08 '18 at 07:38
  • Yeah i got some how near to your point. But, i will not have any login button or any thing which could trigger `signInRedirect()`. I need to trigger that in the main application URL. Currently which i am doing in SignIn Component. But where should i implement the logic to trigger the signInRedirect? What do you suggest? – Rasik Apr 08 '18 at 07:51
  • So what you need is something to call signin redirect when the user tries to access a protected route and is not yet authenticated. In your case all routes but the sigin endpoint are protected. I don't know how to do that in vue but angular has guards which you can set to run before a route is loaded - I guess vue has something similar – mode777 Apr 08 '18 at 08:37
  • Yes vue also has same, which i have shown in my question. `router.beforeEach((to, from, next) => {}`. – Rasik Apr 08 '18 at 08:42
  • Just a quick question. On SignOut do i need to clear the cookies on the browser? Because i am still login when i signout from the identity. – Rasik Apr 09 '18 at 14:00
  • when you access signout on the identity server, it should do this automatically - if you are using aspnet identity. On the client oidc-client should clear the session-storage too – mode777 Apr 09 '18 at 14:08
  • Yeah i am using Asp.net identity. and i was storing access_token on the cookies. But the `this.userManager.signoutRedirect()` is redirecting me but not clearing the cookies. – Rasik Apr 09 '18 at 14:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168569/discussion-between-mode777-and-aakash). – mode777 Apr 09 '18 at 14:12
  • Thanks for your immense help. – Rasik Apr 09 '18 at 14:52
  • Please need your help on this. https://stackoverflow.com/questions/50197603/identity-server-4-claims-empty-on-api – Rasik May 06 '18 at 10:36