-
Notifications
You must be signed in to change notification settings - Fork 232
OktaAuthService.getUser() throws TypeError #192
Comments
Hey @jakehockey10! First, let me recommend what you should/shouldn't cache:
It doesn't, but I like the suggestion! We have an open enhancement to add support for an HTTP interceptor, during which we'd explore adding retry logic, a backoff strategy, etc. Want to create an issue for the enhancements you'd like to see? Regarding the error mentioned in your comment - are you waiting for waiting for the response to resolve? Here is an example of how we are waiting for Hope this helps! |
@jmelberg-okta Thank you so much for the suggestions! I took your suggestions into account and things are working much better for me, thank you! |
In terms of enhancements, I'll think of a better way to phrase it and try to write something up! Thanks! |
As for the error, I'm still seeing it locally and in a deployed dev environment. I think it is IE 11 related though. I don't remember seeing the issue in other browsers. But yes, any time I call |
@jmelberg-okta Some more info on the error: I am indeed using |
@jmelberg-okta Could I talk to you a little bit more about this? I'm still having issues with
It happens way more frequently in IE11. After authenticating through the redirect flow, and as my application is bootstrapping again, the The error seems to be thrown after calling into Any ideas on how I can diagnose this and avoid it in the future? For additional context: Here are the problem areas: ...
export class AppComponent implements OnIt {
...
async ngOnInit() {
// Checking isAuthenticated right here will return true if
// the user logged in a while back and they are coming back
// to the site. It will return false when coming back from
// the login redirect. This method is called prior to
// the change in authentication state is emitted.
this.isAuthenticated = await this._auth.isAuthenticated();
if (this.isAuthenticated) {
this.user = await this._auth.getUser();
if (this.user) {
this._zendesk.identify({
name: this.user.name,
email: this.user.email
});
this._alerts.successOccurred.next(`Hello ${this.user.name}`);
}
}
this._devExtremeTheme.apply(this._settings.theme);
this.mainMenu$ = this._menu.getCurrentMenu();
}
...
private listenToAuthentication() {
this._auth.$authenticationState.subscribe(
async (isAuthenticated: boolean) => {
this.isAuthenticated = isAuthenticated;
if (isAuthenticated) {
this.user = await this._auth.getUser();
if (this.user) {
this._zendesk.identify({
name: this.user.name,
email: this.user.email
});
}
this._zendesk.show();
} else {
this.user = null;
this._zendesk.hide();
}
this.mainMenu$ = this._menu.getCurrentMenu();
}
);
}
...
}
@Injectable()
export class MenuService {
...
getCurrentMenu(): Observable<MenuItem[]> {
return defer(async () => {
let isAuthenticated = false;
try {
isAuthenticated = await this._auth.isAuthenticated();
} catch (e) {
console.error(e);
return this.loggedOutMenu;
}
if (isAuthenticated) {
try {
const user = await this._auth.getUser();
return user ? this.customizedMenu(user) : this.mainMenu;
} catch (e) {
console.error(e);
return this.mainMenu;
}
} else {
return this.loggedOutMenu;
}
});
}
...
} At first, I didn't have all these |
Hey @jakehockey10, My guess is this could be due to a couple of issues. Since this only occurs in IE 11, can you verify that Third-party cookies are enabled? You can see how to via visit this forum post. After a user's The second reason could be that const oktaConfig = {
issuer: 'https://{yourOktaDomain}.com/oauth2/default',
clientId: '{clientId}',
redirectUri: 'http://localhost:{port}/implicit/callback',
responseType: 'id_token token'
} Let me know if this solves the issue! |
Here is my IE 11 settings. I had to add my issuer to the sites collection of trusted sites as well. The only thing I hadn't done was specify the responseType in my oktaConfig. I hadn't had to do this before, while still getting an access token. It's really hard to tell what the problem is because I'm also having live-reload issues with IE. Developing for IE is pretty freaking painful! I have to restart the browser a lot anyway. The issue seems to have calmed down a little bit, but I'm still seeing the issue occasionally. It has to be something I'm doing timing-wise... |
You're most likely running into the race condition described in You can validate this by waiting for your Our team is working on getting this fixed as soon as possible, so I apologize for the inconvenience this is creating. |
Ah that sounds like it could be it. Thanks for helping me curb the feeling of insanity! |
@jmelberg-okta , I'm pulling in |
Here is my import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { OktaAuthService, UserClaims } from '@okta/okta-angular';
import * as OktaAuth from '@okta/okta-auth-js';
import { Subject } from 'rxjs/Subject';
import { environment } from '../../environments/environment';
@Injectable()
export class AuthenticationService {
private _oktaAuth: OktaAuth;
private _user: UserClaims;
tokenRefreshed = new Subject<UserClaims>();
authenticationState = new Subject<boolean>();
constructor(private _router: Router, private _okta: OktaAuthService) {
this._oktaAuth = new OktaAuth({
url: environment.oktaURL.split('/oauth2/')[0],
clientId: environment.oktaClientID,
issuer: environment.oktaURL,
redirectUri: environment.rootURI
});
this._oktaAuth.tokenManager.on(
'refreshed',
async (key, newToken, oldToken) => {
await this.setUser();
this.tokenRefreshed.next(this._user);
}
);
this._oktaAuth.tokenManager.on('error', error => {
console.error(error);
});
this._okta.$authenticationState.subscribe(async isAuthenticated => {
this._user = null;
if (isAuthenticated) {
await this.setUser();
}
this.authenticationState.next(isAuthenticated);
});
}
async isAuthenticated(): Promise<boolean> {
try {
/**
* This returns whether they have an idToken or an accessToken.
* I want `isAuthenticated` to mean whether or not I have
* both an idToken AND an accessToken (preferably not expired).
* I've had this return true when all I had was an accessToken
* (I'm not sure how I got into that state).
*/
const isAuthenticated = await this._okta.isAuthenticated();
const idToken = await this._okta.getIdToken();
return isAuthenticated && !!idToken;
} catch (e) {
console.error(e);
return false;
}
}
async getUser(): Promise<UserClaims> {
if (await this.isAuthenticated) {
if (!this._user) {
await this.setUser();
}
} else {
this._user = null;
}
return this._user;
}
async isAdmin(): Promise<boolean> {
try {
if (await this.isAuthenticated) {
return (
(await this.getUser()
.then<boolean>(
userClaims =>
userClaims &&
userClaims['groups'] &&
userClaims['groups'].includes('admin')
)
.catch(reason => {
console.error(reason);
return false;
})) || false
);
} else {
return false;
}
} catch (e) {
console.error(e);
return false;
}
}
async getAccessToken() {
return this._okta.getAccessToken();
}
login() {
this._okta.loginRedirect(this._router.url, {
scopes: ['groups', 'openid', 'profile', 'email', 'address', 'phone']
});
}
logout(): Promise<void> {
return this._okta
.logout()
.then(() => {
this._router.navigate(['/home']);
})
.catch(reason => {
localStorage.removeItem('okta-token-storage');
});
}
private async setUser(): Promise<void> {
try {
this._user = await this._okta.getUser();
} catch (e) {
this._user = null;
console.error(e);
}
}
} Any suggestions? |
@jmelberg-okta, prior to calling |
This issue was related to a bug that has since been fixed with All of our integration libraries have been updated to pull in this bug-fix, so please update you app accordingly. If the issue persists, please feel free to reopen this issue. |
Issue still persist for edge browser? Please share if someone have solution for this? |
@ShoaibShaukatSystems If so, can you share which SDKs and confirm the experience you see? |
@swiftone |
I'm still having this issue, on Chrome. But maybe it's something I'm doing wrong. After about 1h if I refresh the page I'm getting
The code is below: async ngOnInit() {
this.isAuthenticated = await this.oktaAuth.isAuthenticated();
if (this.isAuthenticated) {
const oktaGetUser = this.oktaAuth.getUser().then(
(userClaims) => this.displayName = userClaims.name
)
}
} |
Hello,
I'm using the latest version of the
@okta/okta-angular
npm package and the interface has changed quite a bit. Some things are now promises while other things are not. And I used to be able to access theTokenManager
. Not sure if that is possible now.But when I use
getUser
from the service, I sometimes get this error:I'm having a little bit of trouble with the new interface because I attempted to wrap the
OktaAuthService
with my ownAuthenticationService
so that I could cache things and have a central location for authentication related questions and activities. Now that things are promise-based (like the access token and user claims object), my app can't initialize in the same way that I have had it initialize before. Not a huge difference, but I wanted to generally asks if I'm approaching this right. Should I be trying to cache the results ofgetUser
,isAuthenticated
,getAccessToken
, etc. or should I be using these methods any time a component or service needs to know the value of them? Does the@okta/okta-angular
library handle excessive calls to remote authorization servers for me?The text was updated successfully, but these errors were encountered: