Skip to content

Commit c97ea5a

Browse files
authored
Fixed several issues around OAuth flows. (#1650)
1 parent b43daf0 commit c97ea5a

File tree

2 files changed

+61
-20
lines changed

2 files changed

+61
-20
lines changed

src/services/oauthService.ts

Lines changed: 42 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import { UnauthorizedError } from "./../errors/unauthorizedError";
21
import * as ClientOAuth2 from "client-oauth2";
3-
import * as Utils from "@paperbits/common";
4-
import { HttpClient, HttpMethod } from "@paperbits/common/http";
52
import { ISettingsProvider } from "@paperbits/common/configuration";
6-
import { GrantTypes } from "./../constants";
7-
import { MapiClient } from "./mapiClient";
3+
import { HttpClient, HttpMethod } from "@paperbits/common/http";
84
import { AuthorizationServerContract } from "../contracts/authorizationServer";
9-
import { AuthorizationServer } from "../models/authorizationServer";
105
import { OpenIdConnectProviderContract } from "../contracts/openIdConnectProvider";
11-
import { OpenIdConnectProvider } from "./../models/openIdConnectProvider";
6+
import { AuthorizationServer } from "../models/authorizationServer";
7+
import { Utils } from "../utils";
8+
import { GrantTypes } from "./../constants";
129
import { OpenIdConnectMetadata } from "./../contracts/openIdConnectMetadata";
10+
import { UnauthorizedError } from "./../errors/unauthorizedError";
11+
import { OpenIdConnectProvider } from "./../models/openIdConnectProvider";
12+
import { MapiClient } from "./mapiClient";
13+
import { KnownHttpHeaders } from "../models/knownHttpHeaders";
14+
import { KnownMimeTypes } from "../models/knownMimeTypes";
1315

1416
export class OAuthService {
1517
private environmentPromise: Promise<string>;
@@ -21,7 +23,7 @@ export class OAuthService {
2123
) { }
2224

2325
private async getEnvironment(): Promise<string> {
24-
if (!this.environmentPromise){
26+
if (!this.environmentPromise) {
2527
this.environmentPromise = this.settingsProvider.getSetting<string>("environment");
2628
}
2729
return this.environmentPromise;
@@ -112,7 +114,7 @@ export class OAuthService {
112114
* @param grantType {string} Requested grant type.
113115
* @param authorizationServer {AuthorizationServer} Authorization server details.
114116
*/
115-
public async authenticate(grantType: string, authorizationServer: AuthorizationServer): Promise<string> {
117+
public async authenticate(grantType: string, authorizationServer: AuthorizationServer, apiName?: string): Promise<string> {
116118
const backendUrl = await this.settingsProvider.getSetting<string>("backendUrl") || `https://${location.hostname}`;
117119

118120
let accessToken;
@@ -127,7 +129,7 @@ export class OAuthService {
127129
break;
128130

129131
case GrantTypes.clientCredentials:
130-
accessToken = await this.authenticateClientCredentials(backendUrl, authorizationServer);
132+
accessToken = await this.authenticateClientCredentials(backendUrl, authorizationServer, apiName);
131133
break;
132134

133135
default:
@@ -173,13 +175,13 @@ export class OAuthService {
173175
return;
174176
}
175177

176-
const oauthToken = await oauthClient.token.getToken(redirectUri + tokenHash);
178+
const tokenInfo = await oauthClient.token.getToken(redirectUri + tokenHash);
177179

178-
if (oauthToken.accessToken) {
179-
resolve(`${oauthToken.tokenType} ${oauthToken.accessToken}`);
180+
if (tokenInfo.accessToken) {
181+
resolve(`${Utils.toTitleCase(tokenInfo.tokenType)} ${tokenInfo.accessToken}`);
180182
}
181-
else if (oauthToken.data?.id_token) {
182-
resolve(`Bearer ${oauthToken.data.id_token}`);
183+
else if (tokenInfo.data?.id_token) {
184+
resolve(`Bearer ${tokenInfo.data.id_token}`);
183185
}
184186
};
185187

@@ -223,7 +225,7 @@ export class OAuthService {
223225

224226
const accessToken = event.data["accessToken"];
225227
const accessTokenType = event.data["accessTokenType"];
226-
resolve(`${accessTokenType} ${accessToken}`);
228+
resolve(`${Utils.toTitleCase(accessTokenType)} ${accessToken}`);
227229
};
228230

229231
window.addEventListener("message", receiveMessage, false);
@@ -239,7 +241,28 @@ export class OAuthService {
239241
* @param backendUrl {string} Portal backend URL.
240242
* @param authorizationServer {AuthorizationServer} Authorization server details.
241243
*/
242-
public async authenticateClientCredentials(backendUrl: string, authorizationServer: AuthorizationServer): Promise<string> {
244+
public async authenticateClientCredentials(backendUrl: string, authorizationServer: AuthorizationServer, apiName: string): Promise<string> {
245+
const response = await this.httpClient.send<any>({
246+
method: HttpMethod.post,
247+
url: `${backendUrl}/signin-oauth/credentials/${apiName}`,
248+
headers: [{ name: KnownHttpHeaders.ContentType, value: KnownMimeTypes.Json }]
249+
});
250+
251+
if (response.statusCode === 200) {
252+
const tokenInfo = response.toObject();
253+
return `${Utils.toTitleCase(tokenInfo.accessTokenType)} ${tokenInfo.accessToken}`;
254+
}
255+
256+
if (response.statusCode === 400) {
257+
const error = response.toObject();
258+
259+
if (error.message !== "Authorization server configuration not found.") { // message from legacy flow
260+
alert(error.message);
261+
return null;
262+
}
263+
}
264+
265+
// Run legacy window-based flow
243266
let uri = `${backendUrl}/signin-oauth/credentials/${authorizationServer.name}`;
244267

245268
if (authorizationServer.scopes) {
@@ -258,7 +281,7 @@ export class OAuthService {
258281

259282
const accessToken = event.data["accessToken"];
260283
const accessTokenType = event.data["accessTokenType"];
261-
resolve(`${accessTokenType} ${accessToken}`);
284+
resolve(`${Utils.toTitleCase(accessTokenType)} ${accessToken}`);
262285
};
263286

264287
window.addEventListener("message", receiveMessage, false);
@@ -290,7 +313,7 @@ export class OAuthService {
290313

291314
const tokenInfo = response.toObject();
292315

293-
return `${tokenInfo.accessTokenType} ${tokenInfo.accessToken}`;
316+
return `${Utils.toTitleCase(tokenInfo.accessTokenType)} ${tokenInfo.accessToken}`;
294317
}
295318

296319
public async discoverOAuthServer(metadataEndpoint: string): Promise<AuthorizationServer> {

src/utils.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,4 +382,22 @@ export class Utils {
382382
reader.readAsArrayBuffer(file);
383383
});
384384
}
385-
}
385+
386+
public static guid(): string {
387+
function s4(): string {
388+
return Math.floor((1 + Math.random()) * 0x10000)
389+
.toString(16)
390+
.substring(1);
391+
}
392+
return s4() + s4() + "-" + s4() + "-" + s4() + "-" +
393+
s4() + "-" + s4() + s4() + s4();
394+
}
395+
396+
public static toTitleCase(value: string): string {
397+
return value
398+
.toLowerCase()
399+
.split(" ")
400+
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
401+
.join(" ");
402+
}
403+
}

0 commit comments

Comments
 (0)