Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions server/auth/types/authentication_type.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class DummyAuthType extends AuthenticationType {
isValidCookie() {
return Promise.resolve(true);
}
refreshAccessToken() {
return Promise.resolve('');
}
requestIncludesAuthInfo() {
return false;
}
Expand Down
21 changes: 17 additions & 4 deletions server/auth/types/authentication_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ export abstract class AuthenticationType implements IAuthenticationType {
cookie = undefined;
}

let newAuthHeaderValue = '';
if (cookie) {
newAuthHeaderValue = await this.refreshAccessToken(cookie, request);
}

if (!cookie || !(await this.isValidCookie(cookie, request))) {
// clear cookie
this.sessionStorageFactory.asScoped(request).clear();
Expand All @@ -160,10 +165,14 @@ export abstract class AuthenticationType implements IAuthenticationType {
}
// cookie is valid
// build auth header
const authHeadersFromCookie = this.buildAuthHeaderFromCookie(cookie!, request);
Object.assign(authHeaders, authHeadersFromCookie);
const additonalAuthHeader = await this.getAdditionalAuthHeader(request);
Object.assign(authHeaders, additonalAuthHeader);
if (!!newAuthHeaderValue) {
Object.assign(authHeaders, { authorization: newAuthHeaderValue });
} else {
const authHeadersFromCookie = this.buildAuthHeaderFromCookie(cookie!, request);
Object.assign(authHeaders, authHeadersFromCookie);
const additonalAuthHeader = await this.getAdditionalAuthHeader(request);
Object.assign(authHeaders, additonalAuthHeader);
}
}

// resolve tenant if necessary
Expand Down Expand Up @@ -277,6 +286,10 @@ export abstract class AuthenticationType implements IAuthenticationType {
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<boolean>;
public abstract refreshAccessToken(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Provide a default implementation that returns empty string?

cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string>;
protected abstract handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
Expand Down
7 changes: 7 additions & 0 deletions server/auth/types/basic/basic_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@ export class BasicAuthentication extends AuthenticationType {
);
}

async refreshAccessToken(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string> {
return '';
}

handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
Expand Down
7 changes: 7 additions & 0 deletions server/auth/types/jwt/jwt_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,13 @@ export class JwtAuthentication extends AuthenticationType {
);
}

async refreshAccessToken(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string> {
return '';
}

handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
Expand Down
12 changes: 12 additions & 0 deletions server/auth/types/multiple/multi_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ export class MultipleAuthentication extends AuthenticationType {
}
}

async refreshAccessToken(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string> {
const reqAuthType = cookie?.authType?.toLowerCase();
if (reqAuthType && this.authHandlers.has(reqAuthType)) {
return this.authHandlers.get(reqAuthType)!.refreshAccessToken(cookie, request);
} else {
return '';
}
}

handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
Expand Down
29 changes: 25 additions & 4 deletions server/auth/types/openid/openid_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,27 @@ export class OpenIdAuthentication extends AuthenticationType {
return true;
}

return false;
}

async refreshAccessToken(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string> {
if (
cookie.authType !== this.type ||
!cookie.username ||
!cookie.expiryTime ||
(!cookie.credentials?.authHeaderValue && !this.getExtraAuthStorageValue(request, cookie)) ||
!cookie.credentials?.expires_at
) {
return '';
}

if (cookie.credentials?.expires_at > Date.now()) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the check on 243, drop the coalescing operator? I'm not sure what this check would resolve to if it wasn't set (for whatever crazy reason). Could you also add unit tests?

Suggested change
if (cookie.credentials?.expires_at > Date.now()) {
if (cookie.credentials.expires_at > Date.now()) {

return '';
}

// need to renew id token
if (cookie.credentials.refresh_token) {
try {
Expand Down Expand Up @@ -248,17 +269,17 @@ export class OpenIdAuthentication extends AuthenticationType {
this.getExtraAuthStorageOptions()
);

return true;
return `Bearer ${refreshTokenResponse.idToken}`;
} else {
return false;
return '';
}
} catch (error: any) {
this.logger.error(error);
return false;
return '';
}
} else {
// no refresh token, and current token is expired
return false;
return '';
}
}

Expand Down
7 changes: 7 additions & 0 deletions server/auth/types/proxy/proxy_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ export class ProxyAuthentication extends AuthenticationType {
);
}

async refreshAccessToken(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string> {
return '';
}

handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
Expand Down
7 changes: 7 additions & 0 deletions server/auth/types/saml/saml_auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ export class SamlAuthentication extends AuthenticationType {
);
}

async refreshAccessToken(
cookie: SecuritySessionCookie,
request: OpenSearchDashboardsRequest
): Promise<string> {
return '';
}

handleUnauthedRequest(
request: OpenSearchDashboardsRequest,
response: LifecycleResponseFactory,
Expand Down