Get Current User api always returns the admin user profile and not the user that is logged in

Hello Okta Folks,

I have two users in Okta.

  1. aakash.banerjee@gmail.com (Super Admin)
  2. aakashbanerjee@outlook.com (User created using Create New User api and activated)

What I am trying to achieve is pretty simple. Once a user logs in to the web app the current logged in users’s email is displayed in navbar, screenshot below.

I am using Angular 5 as the frontend framework btw so below are some code fragments and my thought process.

My navbar component in its ngOnInit() will call a method getuserLoggedin() if oktaAuth.isAuthenticated() is true. This is nothing but a method in my service that pings Okta’s get current user api: https://dev-179941.oktapreview.com/api/v1/users/me

ngOnInit() {
    if(this.oktaAuth.isAuthenticated()){
        this.getcurrentUser.getuserLoggedin().subscribe(data =>{
          console.log(data);
},
(err : HttpErrorResponse) => {
//error handling etc
});

Service Code fragment looks something like this.

@Injectable()
export class FileService {

apikey = 'SSWS myapikey'; 
getuseroktaurl = 'https://dev-179941.oktapreview.com/api/v1/users/me';

constructor(private http: HttpClient, private oktaAuth: OktaAuthService) { }

getuserLoggedin(token) : Observable<any>{
      return this.http.get(this.getuseroktaurl, {
        headers: new HttpHeaders().set('Accept', 'application/json').set('Content-Type', 'application/json').set('Authorization', this.apikey),
      });
}

Now that I have set the stage up for disappointment. Here is whats happening. If I login in with my super admin user aakash.banerjee@gmail.com or a normal user aakashbanerjee@outlook.com the get current user api returns the admin user login so no matter who logs in the navbar shows the admin user email. I am wondering why is that?

On closer look at the browser console below is the error I see first time when the user authenticates and /implicit/callback hits.

ERROR Error: Uncaught (in promise): AuthSdkError: Unable to parse a token from the url
Error
    at Object.../../../../@okta/okta-auth-js/lib/errors/AuthSdkError.js (AuthSdkError.js:26)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/storageBuilder.js (storageBuilder.js:1)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/storageUtil.js (storageUtil.js:2)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/http.js (http.js:4)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/tx.js (tx.js:2)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/errors/AuthSdkError.js (AuthSdkError.js:26)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/storageBuilder.js (storageBuilder.js:1)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/storageUtil.js (storageUtil.js:2)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/http.js (http.js:4)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at Object.../../../../@okta/okta-auth-js/lib/tx.js (tx.js:2)
    at __webpack_require__ (bootstrap d941f41afcbce05d7983:54)
    at resolvePromise (zone.js:824)
    at zone.js:746
    at rejected (okta.service.js:24)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:392)
    at Object.onInvoke (core.js:4753)
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
    at Zone.webpackJsonp.../../../../zone.js/dist/zone.js.Zone.run (zone.js:142)
    at zone.js:873
    at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:425)
    at Object.onInvokeTask (core.js:4744)

I investigated my api token that I am passing to the api authorization header. This was created by my super admin user. Do I have to pass something else as apitoken for every user? Instead of passing my super admin apitoken I tried passing the accessToken for the current user to the api and obviously it returns a 403.

So if you guys have come across this issue and have resolved it some way your help is much appreciated.

Thank you.

Aakash.

1 Like

Hey @aakashb! I think we’re confusing a few things here - so let me try and help.

The okta-angular SDK provides you the ability add OAuth 2.0 and OpenID Connect into your Angular app. The method isAuthenticated() looks for an accessToken or idToken in your browser storage. In practice, you should be hitting the /userinfo endpoint to retrieve user information, as opposed to directly calling the /users/me endpoint.

NOTE: Please do not include your API_TOKEN inside of a public application - as this value will be visible to anyone who loads your site.

Try using something similar to this code block inside of your ngOnInit() function:

ngOnInit() {
  if (this.oktaAuth.isAuthenticated()) {
    const accessToken = this.oktaAuth.getAccessToken().accessToken
    
    // Get user information
    const userInfo = this.oktaAuth.getOktaAuth().token.getUserInfo(accessToken) : undefined
    
    // Update the UI with userInfo.email
  }
}

Regarding the Unable to parse a token from the url error - this is usually seen when there is an error attempting to authenticate, as an accesToken and/or idToken isn’t returned successfully. Make sure your users are logged out using the oktaAuth.logout() method.

For a sample use case of setting up an Angular app with Okta, you can check out the quickstart guide.

Hope this removes a few blockers!

To add to what @jmelberg already said, when you send an API key in the auth header to the /users/me, it will return the user associated with the API key. In your case, since you generated the key for the super user, it will always returns the super users information. But as already mentioned, never store API keys in front-end code. Also, try calling the endpoint without passing the auth header, and you should see the user who is logged in, in the response.

Thank you.

However, when I add the code below to my navbar component ngOnInit(), the console log accessToken is displayed that the token was found. However it throws an error in the console which is below. [name: “AuthSdkError”, message: “getUserInfo requires an access token object”]

ngOnInit() {
  if (this.oktaAuth.isAuthenticated()) {
    const accessToken = this.oktaAuth.getAccessToken().accessToken
    console.log(accessToken); //accessToken is displayed in console.
    
    // Get user information
    const userInfo = this.oktaAuth.getOktaAuth().token.getUserInfo(accessToken); //I thought I am passing the accessToken here so getUserInfo should have what it needs right?
    console.log(userInfo);
    this.loginaccount = userInfo.email;
    
    // Update the UI with userInfo.email
  }
}

Promise {promiseDispatch: ƒ, inspect: ƒ, exception: AuthSdkError, valueOf: ƒ}
exception
:
AuthSdkError {name: "AuthSdkError", message: "getUserInfo requires an access token object", errorCode: "INTERNAL", errorSummary: "getUserInfo requires an access token object", errorLink: "INTERNAL", …}
inspect
:
ƒ inspect()
promiseDispatch
:
ƒ (resolve, op, args)
valueOf
:
ƒ ()
__proto__
:
Object

Hi Vijet, Not passing the auth header returns a 403 as expected. Aakash.

Also here is my logout() code which does call the oktaAuth.logout()

logOut(){
    this.oktaAuth.logout();
    this.router.navigateByUrl("/home", {replaceUrl:true});
  }

You’re passing the accessToken string. Instead, you must pass the accessToken object as follows -

const userInfo = this.oktaAuth.getOktaAuth().token.getUserInfo(this.oktaAuth.getAccessToken())

Let us know if this works.

Thanks Vijet. When I pass the object instead of the string the error - getUserInfo requires an accessToken is not logged anymore.

However when i do a console.log(userInfo) below is what is logged. Is this supposed to be Promise?

Promise {promiseDispatch: ƒ, valueOf: ƒ, inspect: ƒ}
inspect
:
ƒ ()
promiseDispatch
:
ƒ (resolve, op, operands)
source
:
Promise {promiseDispatch: ƒ, inspect: ƒ, valueOf: ƒ}
valueOf
:
ƒ ()
__proto__
:
Object

Also when I inspected the Network log in Chrome. I see that it is returning the required userInfo. I am trying to figure out how to get that info and use it in Angular.

Yes Aakash, it does return a promise.
Take a look at the documentation here - https://github.com/okta/okta-auth-js#tokengetuserinfoaccesstokenobject

Thank you @vijet. So now it works but… Below is the code that I have on my Navbar component’s ngOnInit() if this helps someone.
The login email of the user does get set but there is a slight delay and/or they have to click on something / anything on the browser. Interesting but weird.

ngOnInit() {

console.log(this.oktaAuth.isAuthenticated());

if(this.oktaAuth.isAuthenticated()){

    const accessToken = this.oktaAuth.getAccessToken().accessToken;
    console.log(accessToken);
    this.oktaAuth.getOktaAuth().token.getUserInfo(this.oktaAuth.getAccessToken()).then(user => {
      console.log(user.email);
      this.loginaccount = user.email;
    });
  }

}

Here is my template code where I set my loginaccount in the navbar.

<li class="nav-item">
  <a role="button" class="nav-link waves-light" mdbRippleRadius *ngIf="oktaAuth.isAuthenticated()">{{loginaccount}}</a>
</li>

Once the user logs in this is what they see.

Once they click or touch anything on the browser below is what they see. At this point the correct value of the login email appears on the navbar but with a delay. Any specific lifecycle hook that could resolve this on Angular.

Let me know if you have seen this before.

Try injecting Angular’s ChangeDetectorRef into your component as a dependency, then call the following after this.loginaccount = ...:

this.changeDetectorRef.detectChanges();

I experienced the same “nothing happens issue” without this. I recently updated my Build an Angular App with Okta’s Sign-In Widget in 15 Minutes to have this change. You can see the code changes I made on GitHub.

1 Like

@mraible thanks for this note. ChangeDetectorRef solves this issue.

The component as dependency following the current user api always want to know the admin user profile while logged in so can’t load xpcom for that the upgraded part is having the template code for accessing it.