77 UserManagerSettings ,
88 WebStorageStateStore ,
99} from 'oidc-client-ts' ;
10- import axios from 'axios' ;
11- import jwt_decode from 'jwt-decode' ;
1210import localForage from 'localforage' ;
1311import {
1412 Detail ,
@@ -35,17 +33,45 @@ import {
3533import EmbeddedLoginPrompt from './login/embeddedLoginPrompt' ;
3634import TypedEventEmitter from './utils/typedEventEmitter' ;
3735import { withMetricsAsync } from './utils/metrics' ;
36+ import { decodeJwtPayload } from './utils/jwt' ;
3837import DeviceCredentialsManager from './storage/device_credentials_manager' ;
3938import { PassportError , PassportErrorType , withPassportError } from './errors' ;
4039import logger from './utils/logger' ;
4140import { isAccessTokenExpiredOrExpiring } from './utils/token' ;
4241import LoginPopupOverlay from './overlay/loginPopupOverlay' ;
4342import { LocalForageAsyncStorage } from './storage/LocalForageAsyncStorage' ;
4443
45- const formUrlEncodedHeader = {
46- headers : {
47- 'Content-Type' : 'application/x-www-form-urlencoded' ,
48- } ,
44+ const formUrlEncodedHeaders = {
45+ 'Content-Type' : 'application/x-www-form-urlencoded' ,
46+ } ;
47+
48+ const parseJsonSafely = ( text : string ) : unknown => {
49+ if ( ! text ) {
50+ return undefined ;
51+ }
52+ try {
53+ return JSON . parse ( text ) ;
54+ } catch {
55+ return undefined ;
56+ }
57+ } ;
58+
59+ const extractTokenErrorMessage = (
60+ payload : unknown ,
61+ fallbackText : string ,
62+ status : number ,
63+ ) : string => {
64+ if ( payload && typeof payload === 'object' ) {
65+ const data = payload as Record < string , unknown > ;
66+ const description = data . error_description ?? data . message ?? data . error ;
67+ if ( typeof description === 'string' && description . trim ( ) . length > 0 ) {
68+ return description ;
69+ }
70+ }
71+ if ( fallbackText . trim ( ) . length > 0 ) {
72+ return fallbackText ;
73+ }
74+ return `Token request failed with status ${ status } ` ;
4975} ;
5076
5177const logoutEndpoint = '/v2/logout' ;
@@ -523,7 +549,7 @@ export class Auth {
523549 let passport : PassportMetadata | undefined ;
524550 let username : string | undefined ;
525551 if ( oidcUser . id_token ) {
526- const idTokenPayload = jwt_decode < IdTokenPayload > ( oidcUser . id_token ) ;
552+ const idTokenPayload = decodeJwtPayload < IdTokenPayload > ( oidcUser . id_token ) ;
527553 passport = idTokenPayload ?. passport ;
528554 if ( idTokenPayload ?. username ) {
529555 username = idTokenPayload ?. username ;
@@ -552,7 +578,7 @@ export class Auth {
552578 } ;
553579
554580 private static mapDeviceTokenResponseToOidcUser = ( tokenResponse : DeviceTokenResponse ) : OidcUser => {
555- const idTokenPayload : IdTokenPayload = jwt_decode ( tokenResponse . id_token ) ;
581+ const idTokenPayload : IdTokenPayload = decodeJwtPayload ( tokenResponse . id_token ) ;
556582 return new OidcUser ( {
557583 id_token : tokenResponse . id_token ,
558584 access_token : tokenResponse . access_token ,
@@ -650,18 +676,39 @@ export class Auth {
650676 }
651677
652678 private async getPKCEToken ( authorizationCode : string , codeVerifier : string ) : Promise < DeviceTokenResponse > {
653- const response = await axios . post < DeviceTokenResponse > (
679+ const response = await fetch (
654680 `${ this . config . authenticationDomain } /oauth/token` ,
655681 {
656- client_id : this . config . oidcConfiguration . clientId ,
657- grant_type : 'authorization_code' ,
658- code_verifier : codeVerifier ,
659- code : authorizationCode ,
660- redirect_uri : this . config . oidcConfiguration . redirectUri ,
682+ method : 'POST' ,
683+ headers : formUrlEncodedHeaders ,
684+ body : new URLSearchParams ( {
685+ client_id : this . config . oidcConfiguration . clientId ,
686+ grant_type : 'authorization_code' ,
687+ code_verifier : codeVerifier ,
688+ code : authorizationCode ,
689+ redirect_uri : this . config . oidcConfiguration . redirectUri ,
690+ } ) ,
661691 } ,
662- formUrlEncodedHeader ,
663692 ) ;
664- return response . data ;
693+
694+ const responseText = await response . text ( ) ;
695+ const parsedBody = parseJsonSafely ( responseText ) ;
696+
697+ if ( ! response . ok ) {
698+ throw new Error (
699+ extractTokenErrorMessage (
700+ parsedBody ,
701+ responseText ,
702+ response . status ,
703+ ) ,
704+ ) ;
705+ }
706+
707+ if ( ! parsedBody || typeof parsedBody !== 'object' ) {
708+ throw new Error ( 'Token endpoint returned an invalid response' ) ;
709+ }
710+
711+ return parsedBody as DeviceTokenResponse ;
665712 }
666713
667714 private async storeTokensInternal ( tokenResponse : DeviceTokenResponse ) : Promise < User > {
0 commit comments