✅Added more test and logs for logout token verification
This commit is contained in:
committed by
Anton Shepilov
parent
cebd02a964
commit
28370cd3ca
@@ -100,9 +100,7 @@ export class OidcJwtVerifier {
|
|||||||
|
|
||||||
async verifyLogoutToken(logoutTokenString: string) {
|
async verifyLogoutToken(logoutTokenString: string) {
|
||||||
const jwt = await this.verifyAsPromise(logoutTokenString);
|
const jwt = await this.verifyAsPromise(logoutTokenString);
|
||||||
// verifyAudience(expectedClientId, jwt.claims.aud);
|
logger.info(`issuer is ${this.issuer} -- ${jwt.claims.iss} -- ${JSON.stringify(jwt)}`);
|
||||||
// verifyIssuer(this.issuer, jwt.claims.iss);
|
|
||||||
|
|
||||||
return jwt;
|
return jwt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,16 +281,36 @@ export class ConsoleRemoteClient implements ConsoleServiceClient {
|
|||||||
async backChannelLogout(logoutToken: string): Promise<void> {
|
async backChannelLogout(logoutToken: string): Promise<void> {
|
||||||
const payload = await this.verifier.verifyLogoutToken(logoutToken);
|
const payload = await this.verifier.verifyLogoutToken(logoutToken);
|
||||||
|
|
||||||
if (!payload.iss || !payload.aud || !payload.iat || !payload.jti || !payload.events) {
|
if (!payload.iss) {
|
||||||
throw new CrudException("Missing required claims", 400);
|
throw new CrudException("Missing required 'iss' claim", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!payload.aud) {
|
||||||
|
throw new CrudException("Missing required 'aud' claim", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!payload.iat) {
|
||||||
|
throw new CrudException("Missing required 'iat' claim", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!payload.jti) {
|
||||||
|
throw new CrudException("Missing required 'jti' claim", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!payload.events) {
|
||||||
|
throw new CrudException("Missing required 'events' claim", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload.nonce) {
|
if (payload.nonce) {
|
||||||
throw new CrudException("Nonce claim is prohibited", 400);
|
throw new CrudException("Nonce claim is prohibited", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!payload.sub && !payload.sid) {
|
if (!payload.sub) {
|
||||||
throw new CrudException("Missing sub or sid claim", 400);
|
throw new CrudException("Missing 'sub' claim", 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!payload.sid) {
|
||||||
|
throw new CrudException("Missing 'sid' claim", 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sessionRepository = gr.services.console.getSessionRepo();
|
const sessionRepository = gr.services.console.getSessionRepo();
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
import { describe, expect, it } from "@jest/globals";
|
||||||
|
// @ts-ignore
|
||||||
|
import _ from "lodash";
|
||||||
|
import { ConsoleRemoteClient } from "../../../../../src/services/console/clients/remote";
|
||||||
|
import { OidcJwtVerifier } from "../../../../../src/services/console/clients/remote-jwks-verifier";
|
||||||
|
import { ConsoleServiceImpl } from "../../../../../src/services/console/service";
|
||||||
|
|
||||||
|
describe("Test back-channel logout", () => {
|
||||||
|
|
||||||
|
const subj = new ConsoleRemoteClient(new ConsoleServiceImpl({
|
||||||
|
audience: "",
|
||||||
|
authority: "",
|
||||||
|
client_id: "",
|
||||||
|
client_secret: "",
|
||||||
|
disable_account_creation: false,
|
||||||
|
jwks_uri: "",
|
||||||
|
redirect_uris: [],
|
||||||
|
type: undefined,
|
||||||
|
issuer: "" }));
|
||||||
|
const verifyTokenMock = jest.spyOn(OidcJwtVerifier.prototype, "verifyLogoutToken");
|
||||||
|
|
||||||
|
const validToken = {
|
||||||
|
"sid": "Ev81/QODom0HXu9MGjCwnn1tDTpji+j0jopjRAE0ypo",
|
||||||
|
"aud": [
|
||||||
|
"twakedrive"
|
||||||
|
],
|
||||||
|
"sub": "shepilov3@stg.lin-saas.com",
|
||||||
|
"iat": 1716986356,
|
||||||
|
"jti": "F9R6DYPE",
|
||||||
|
"events": {
|
||||||
|
"http://schemas.openid.net/event/backchannel-logout": {}
|
||||||
|
},
|
||||||
|
"iss": "https://sign-up.stg.lin-saas.com/"
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockTokenWithoutProperty = (prop: string) => {
|
||||||
|
const token = _.cloneDeep(validToken);
|
||||||
|
token[prop] = null
|
||||||
|
verifyTokenMock.mockImplementation(() => {
|
||||||
|
return Promise.resolve(token); // Return the predefined payload
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'iss' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("iss")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrow("Missing required 'iss' claim");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'aud' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("aud")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrow("Missing required 'aud' claim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'jti' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("jti")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrow("Missing required 'jti' claim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'iat' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("iat")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrow("Missing required 'iat' claim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'events' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("events")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrowError("Missing required 'events' claim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'sub' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("sub")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrowError("Missing 'sub' claim");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("backChannelLogout should throw error if 'sid' claim is missing", () => {
|
||||||
|
//given
|
||||||
|
mockTokenWithoutProperty("sid")
|
||||||
|
//when
|
||||||
|
let logout = subj.backChannelLogout('');
|
||||||
|
//then
|
||||||
|
expect(logout).rejects.toThrowError("Missing 'sid' claim");
|
||||||
|
});
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user