44 */
55import { toast } from 'react-toastify' ;
66
7+ const oauthResponseHtml = 'oauthResponse.html' ; // only used for new tab auth
78const expirationBuffer = 10 * 60 ; // 10 minute buffer
89const sdkString = 'codeEg_react' ;
910const urlFrag = '/restapi/v2.1' ; // DocuSign specific
@@ -34,15 +35,15 @@ class OAuthImplicit {
3435 //
3536 constructor ( app ) {
3637 this . app = app ;
38+ this . oauthWindow = null ; // only used for new tab auth
3739 }
3840
3941 /**
4042 * Handle incoming OAuth Implicit grant response
4143 */
42- async completeLogin ( ) {
44+ async receiveHash ( hash ) {
4345 const config = window . config ;
44- const hash = window . location . hash
45- , accessTokenFound = hash && hash . substring ( 0 , 14 ) === '#access_token=' ;
46+ const accessTokenFound = hash && hash . substring ( 0 , 14 ) === '#access_token=' ;
4647 if ( ! accessTokenFound ) { return } // EARLY RETURN
4748
4849 // Avoiding an injection attack: check that the hash only includes expected characters
@@ -70,10 +71,18 @@ class OAuthImplicit {
7071 console . error ( `OAuth state mismatch!! Expected state: ${ oauthStateValue } ; received state: ${ incomingState } ` ) ;
7172 return // EARLY RETURN
7273 }
73- // hash was good, so erase it from the browser
74- window . history . replaceState ( null , '' , config . DS_APP_URL ) ;
7574 window . localStorage . clear ( ) ; // clean up
7675
76+ if ( config . DS_REDIRECT_AUTHENTICATION ) {
77+ // Using redirect the window authentication:
78+ // hash was good, so erase it from the browser
79+ window . history . replaceState ( null , '' , config . DS_APP_URL ) ;
80+ } else {
81+ // Using new tab authentication:
82+ // close the tab that was used for authentication
83+ if ( this . oauthWindow ) { this . oauthWindow . close ( ) }
84+ }
85+
7786 // calculate expires
7887 let expires = new Date ( )
7988 expires . setTime ( expires . getTime ( ) + ( expiresIn - expirationBuffer ) * 1000 )
@@ -96,10 +105,8 @@ class OAuthImplicit {
96105 }
97106 //
98107 // Need to select the right proxy for the API call
99- let baseUri ;
100- if ( defaultAccount . base_uri === config . DS_API_CORS_PROXY_FOR ) {
101- baseUri = config . DS_API_CORS_PROXY ;
102- }
108+ // update the baseUri setting
109+ let baseUri = config . DS_API_CORS_PROXIES [ defaultAccount . base_uri ] ;
103110 if ( ! baseUri ) {
104111 const msg = `Problem: no proxy for ${ defaultAccount . base_uri } .` ;
105112 log ( msg ) ;
@@ -118,26 +125,44 @@ class OAuthImplicit {
118125 accountId : defaultAccount . account_id ,
119126 externalAccountId,
120127 accountName : defaultAccount . account_name ,
121- baseUri : defaultAccount . base_uri ,
128+ baseUri : baseUri ,
122129 } )
123130 }
124131
125132 /**
126133 * Start the login flow by computing the Implicit grant URL
127- * and redirecting to the URL for the user.
134+ * and either redirecting to the URL for the user or
135+ * creating a new browser tab for the authentication flow
128136 */
129137 startLogin ( ) {
138+ const config = window . config ;
130139 const oauthStateValue = OAuthImplicit . generateId ( ) ;
131140 window . localStorage . setItem ( oauthState , oauthStateValue ) ; // store for when we come back
132- const url =
133- `${ window . config . DS_IDP } /oauth/auth?` +
134- `response_type=token&` +
135- `scope=${ window . config . IMPLICIT_SCOPES } &` +
136- `client_id=${ window . config . DS_CLIENT_ID } &` +
137- `state=${ oauthStateValue } &` +
138- `redirect_uri=${ encodeURIComponent ( window . config . DS_APP_URL ) } ` ;
141+ let redirectUrl ;
142+ if ( config . DS_REDIRECT_AUTHENTICATION ) {
143+ // Using redirect the window authentication:
144+ redirectUrl = config . DS_APP_URL ;
145+ } else {
146+ // Using new tab authentication
147+ redirectUrl = `${ config . DS_APP_URL } /${ oauthResponseHtml } ` ;
148+ }
139149
140- window . location = url ;
150+ const url =
151+ `${ window . config . DS_IDP } /oauth/auth?` +
152+ `response_type=token&` +
153+ `scope=${ window . config . IMPLICIT_SCOPES } &` +
154+ `client_id=${ window . config . DS_CLIENT_ID } &` +
155+ `state=${ oauthStateValue } &` +
156+ `redirect_uri=${ encodeURIComponent ( redirectUrl ) } ` ;
157+
158+ if ( config . DS_REDIRECT_AUTHENTICATION ) {
159+ // Using redirect the window authentication:
160+ window . location = url ;
161+ } else {
162+ // Using new tab authentication:
163+ // Create a new tab for authentication
164+ this . oauthWindow = window . open ( url , "_blank" ) ;
165+ }
141166 }
142167
143168 /**
@@ -146,15 +171,14 @@ class OAuthImplicit {
146171 * browser back to this app
147172 */
148173 logout ( ) {
174+ const config = window . config ;
149175 const url =
150- `${ window . config . DS_IDP } /logout?` +
151- //`response_type=code&` +
152- `response_type=token&` +
153- `scope=${ window . config . IMPLICIT_SCOPES } &` +
154- `client_id=${ window . config . DS_CLIENT_ID } &` +
155- `redirect_uri=${ encodeURIComponent ( window . config . DS_APP_URL ) } &` +
156- `response_mode=logout_redirect` ;
157-
176+ `${ window . config . DS_IDP } /logout?` +
177+ `response_type=token&` +
178+ `scope=${ config . IMPLICIT_SCOPES } &` +
179+ `client_id=${ config . DS_CLIENT_ID } &` +
180+ `redirect_uri=${ encodeURIComponent ( config . DS_APP_URL ) } &` +
181+ `response_mode=logout_redirect` ;
158182 window . location = url ;
159183 }
160184
@@ -167,7 +191,7 @@ class OAuthImplicit {
167191 let userInfoResponse
168192 try {
169193 userInfoResponse = await fetch (
170- `${ window . config . DS_AUTHENTICATION } /oauth/userinfo` , {
194+ `${ window . config . DS_IDP } /oauth/userinfo` , {
171195 headers : new Headers ( {
172196 Authorization : `Bearer ${ this . accessToken } ` ,
173197 Accept : `application/json` ,
0 commit comments