jsonwebtoken#decode TypeScript Examples
The following examples show how to use
jsonwebtoken#decode.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: server.ts From one-platform with MIT License | 6 votes |
getServer = () => {
/* Create GraphQL Server */
const server = new ApolloServer({
schema,
context: ({ req }) => {
const userId = req.headers['x-op-user-id'];
let roles = req.headers['x-op-user-roles']
if (typeof roles === 'string') {
roles = roles.split(',').map(role => role.trim());
}
const tokenHeader = req.headers['x-op-token'];
const token = Array.isArray(tokenHeader) ? tokenHeader.join('') : tokenHeader;
const decodedToken = token ? decode(token) : null;
let user = {};
if (!!decodedToken && typeof decodedToken !== 'string') {
user = {
id: decodedToken[TOKEN_USER_ID_FIELD],
name: decodedToken[TOKEN_NAME_FIELD],
username: decodedToken[TOKEN_USERNAME_FIELD],
email: decodedToken[TOKEN_EMAIL_FIELD],
};
}
return {
userId,
roles,
token,
user,
};
},
plugins: [ApolloServerPluginInlineTrace()],
debug: NODE_ENV !== 'production',
});
return server;
}
Example #2
Source File: EnsureAuthenticatedMiddleware.ts From umbriel with MIT License | 6 votes |
async handle(
request: EnsureAuthenticatedMiddlewareRequest
): Promise<HttpResponse> {
try {
const { accessToken } = request
if (accessToken) {
try {
const decoded = decode(accessToken) as DecodedJwt
return ok({ userId: decoded.sub })
} catch (err) {
return forbidden(new AccessDeniedError())
}
}
return forbidden(new AccessDeniedError())
} catch (error) {
return fail(error)
}
}
Example #3
Source File: client_credentials.grant.spec.ts From ts-oauth2-server with MIT License | 6 votes |
export function expectTokenResponse(tokenResponse: ResponseInterface) {
const decodedToken: any = decode(tokenResponse.body.access_token);
expect(tokenResponse.status).toBe(200);
expect(tokenResponse.headers["cache-control"]).toBe("no-store");
expect(tokenResponse.headers["pragma"]).toBe("no-cache");
expect(tokenResponse.body.token_type).toBe("Bearer");
expect(tokenResponse.body.expires_in).toBe(3600);
expect(tokenResponse.body.access_token).toMatch(REGEX_ACCESS_TOKEN);
expect(decodedToken.exp).toBeTruthy();
expect(decodedToken.jti).toBeTruthy();
return decodedToken;
}
Example #4
Source File: permissions.ts From gobarber-project with MIT License | 6 votes |
async function decoder(request: Request): Promise<User | undefined> {
const authHeader = request.headers.authorization || "";
const userRepository = getCustomRepository(UserRepository);
const [, token] = authHeader?.split(" ");
const payload = decode(token);
const user = await userRepository.findOne(payload?.sub, {
relations: ["roles"],
});
return user;
}
Example #5
Source File: MiddlewareAdapter.ts From keycloak-lambda-authorizer with Apache License 2.0 | 6 votes |
getTokenString(req:any) {
const tokenString = req.headers.authorization;
if (!tokenString) {
throw new Error('Expected \'headers.authorization\' parameter to be set');
}
const match = tokenString.match(/^Bearer (.*)$/i);
if (!match || match.length < 2) {
throw new Error(`Invalid Authorization token - '${tokenString}' does not match 'Bearer .*'`);
}
req.jwt = {token: match[1], payload: decode(match[1])};
return match[1];
}
Example #6
Source File: JWT.ts From ZenTS with MIT License | 5 votes |
public static decode<T>(token: string): T {
return decode(token, {
json: true,
}) as T
}
Example #7
Source File: authorization_server.spec.ts From ts-oauth2-server with MIT License | 4 votes |
// base64urlencode(crypto.createHash("sha256").update(codeVerifier).digest());
describe("authorization_server", () => {
let authorizationServer: AuthorizationServer;
let refreshGrant: RefreshTokenGrant;
let user: OAuthUser;
let client: OAuthClient;
let accessToken: OAuthToken;
let scope1: OAuthScope;
let scope2: OAuthScope;
beforeEach(() => {
authorizationServer = new AuthorizationServer(
inMemoryAuthCodeRepository,
inMemoryClientRepository,
inMemoryAccessTokenRepository,
inMemoryScopeRepository,
inMemoryUserRepository,
new JwtService("secret-key"),
);
refreshGrant = authorizationServer.getGrant("refresh_token");
authorizationServer.enableGrantType("authorization_code");
authorizationServer.enableGrantType("client_credentials");
authorizationServer.enableGrantType("implicit");
authorizationServer.enableGrantType("password");
authorizationServer.enableGrantType("refresh_token");
user = { id: "abc123" };
scope1 = { name: "scope-1" };
scope2 = { name: "scope-2" };
client = {
id: "1",
name: "test client",
secret: "super-secret-secret",
redirectUris: ["http://localhost"],
allowedGrants: ["client_credentials"],
scopes: [],
};
inMemoryDatabase.scopes[scope1.name] = scope1;
inMemoryDatabase.scopes[scope2.name] = scope2;
inMemoryDatabase.users[user.id] = user;
});
it("can enable client_credentials grant", async () => {
// arrange
inMemoryDatabase.clients[client.id] = client;
const basicAuth = "Basic " + base64encode(`${client.id}:${client.secret}`);
const request = new OAuthRequest({
headers: {
authorization: basicAuth,
},
body: {
grant_type: "client_credentials",
},
});
// act
const tokenResponse = await authorizationServer.respondToAccessTokenRequest(request);
// assert
expectTokenResponse(tokenResponse);
});
it("validateAuthorizationRequest", async () => {
client = {
id: "authcodeclient",
name: "test auth code client",
secret: undefined,
redirectUris: ["http://localhost"],
allowedGrants: ["authorization_code"],
scopes: [scope1, scope2],
};
inMemoryDatabase.clients[client.id] = client;
const request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "http://localhost",
scope: "scope-1 scope-2",
state: "state-is-a-secret",
code_challenge: codeChallenge,
code_challenge_method: "S256",
},
});
const authorizationRequest = await authorizationServer.validateAuthorizationRequest(request);
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://localhost");
expect(authorizationRequest.state).toBe("state-is-a-secret");
expect(authorizationRequest.codeChallenge).toBe(codeChallenge);
expect(authorizationRequest.codeChallengeMethod).toBe("S256");
expect(authorizationRequest.scopes).toStrictEqual([scope1, scope2]);
});
it("is successful", async () => {
client = {
id: "authcodeclient",
name: "test auth code client",
secret: undefined,
redirectUris: ["http://localhost"],
allowedGrants: ["authorization_code"],
scopes: [scope1, scope2],
};
inMemoryDatabase.clients[client.id] = client;
const authorizationRequest = new AuthorizationRequest("authorization_code", client, "http://localhost");
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.codeChallengeMethod = "S256";
authorizationRequest.codeChallenge = codeChallenge;
authorizationRequest.user = user;
const response = await authorizationServer.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(response.headers.location.split("?")[1]);
const decodedCode: IAuthCodePayload = <IAuthCodePayload>decode(String(authorizeResponseQuery.code));
expect(decodedCode.client_id).toBe(client.id);
expect(decodedCode.redirect_uri).toBe("http://localhost");
});
describe("option requirePKCE", () => {
beforeEach(() => {
client = {
id: "authcodeclient",
name: "test auth code client",
secret: undefined,
redirectUris: ["http://localhost"],
allowedGrants: ["authorization_code"],
scopes: [scope1, scope2],
};
inMemoryDatabase.clients[client.id] = client;
});
test("auth server that does not requirePKCE succeeds for request without code_challenge", async () => {
authorizationServer.setOptions({ requiresPKCE: false });
authorizationServer.enableGrantType("authorization_code");
const request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
scope: scope1.name,
state: "state-is-a-secret",
},
});
// act
const validResponse = await authorizationServer.validateAuthorizationRequest(request);
validResponse.user = user;
validResponse.isAuthorizationApproved = true;
const response = await authorizationServer.completeAuthorizationRequest(validResponse);
// assert
const authorizeResponseQuery = querystring.parse(response.headers.location.split("?")[1]);
const decodedCode: IAuthCodePayload = <IAuthCodePayload>decode(String(authorizeResponseQuery.code));
expect(decodedCode.client_id).toBe(client.id);
expect(decodedCode.redirect_uri).toBe("http://localhost");
expect(decodedCode.code_challenge).toBeUndefined();
});
test("auth server requiring pkce throws if request is missing code_challenge", async () => {
authorizationServer = new AuthorizationServer(
inMemoryAuthCodeRepository,
inMemoryClientRepository,
inMemoryAccessTokenRepository,
inMemoryScopeRepository,
inMemoryUserRepository,
new JwtService("secret-key"),
);
authorizationServer.enableGrantType("authorization_code");
const request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
scope: scope1.name,
state: "state-is-a-secret",
},
});
// act
const response = authorizationServer.validateAuthorizationRequest(request);
// assert
await expect(response).rejects.toThrowError(
/The authorization server requires public clients to use PKCE RFC-7636/,
);
});
});
it("respondToAccessTokenRequest is successful", async () => {
// arrange
client = {
id: "a854eb18-c3df-41a3-ab6b-5d96f787f105",
name: "test client",
secret: "super-secret-secret",
redirectUris: ["http://localhost"],
allowedGrants: ["refresh_token"],
scopes: [scope1, scope2],
};
accessToken = {
accessToken: "176fa0a5-acc7-4ef7-8ff3-17cace20f83e",
accessTokenExpiresAt: DateInterval.getDateEnd("1h"),
refreshToken: "8a0d01db-4da7-4250-8f18-f6c096b1912e",
refreshTokenExpiresAt: DateInterval.getDateEnd("1h"),
client,
scopes: [scope1, scope2],
};
inMemoryDatabase.clients[client.id] = client;
inMemoryDatabase.tokens[accessToken.accessToken] = accessToken;
const bearerResponse = await refreshGrant.makeBearerTokenResponse(client, accessToken);
const request = new OAuthRequest({
body: {
grant_type: "refresh_token",
client_id: client.id,
client_secret: client.secret,
refresh_token: bearerResponse.body.refresh_token,
scope: "scope-1",
},
});
// act
const tokenResponse = await authorizationServer.respondToAccessTokenRequest(request);
// assert
expectTokenResponse(tokenResponse);
expect(tokenResponse.body.scope).toBe("scope-1");
});
});
Example #8
Source File: auth_code.grant.spec.ts From ts-oauth2-server with MIT License | 4 votes |
describe("authorization_code grant", () => {
let user: OAuthUser;
let client: OAuthClient;
let scope1: OAuthScope;
let grant: AuthCodeGrant;
let request: OAuthRequest;
const codeVerifier = "qqVDyvlSezXc64NY5Rx3BbL_aT7c2xEBgoJP9domepFZLEjo9ln8EA"; // base64urlencode(crypto.randomBytes(40));
const codeChallenge = "hA3IxucyJC0BsZH9zdYvGeK0ck2dC-seLBn20l18Iws"; // base64urlencode(crypto.createHash("sha256").update(codeVerifier).digest());
beforeEach(() => {
request = new OAuthRequest();
user = { id: "abc123", email: "[email protected]" };
scope1 = { name: "scope-1" };
client = {
id: "authcodeclient",
name: "test auth code client",
secret: undefined,
redirectUris: ["http://example.com"],
allowedGrants: ["authorization_code"],
scopes: [],
};
grant = new AuthCodeGrant(
inMemoryAuthCodeRepository,
inMemoryClientRepository,
inMemoryAccessTokenRepository,
inMemoryScopeRepository,
inMemoryUserRepository,
new JwtService("secret-key"),
);
inMemoryDatabase.clients[client.id] = client;
inMemoryDatabase.users[user.id] = user;
inMemoryDatabase.scopes[scope1.name] = scope1;
});
describe("can respond to authorization request", () => {
let validQueryData: any;
beforeEach(() => {
validQueryData = {
response_type: "code",
client_id: client.id,
redirect_uri: "http://example.com",
state: "state-is-a-secret",
code_challenge: codeChallenge,
code_challenge_method: "S256",
};
});
it("returns true for valid request", async () => {
request = new OAuthRequest({ query: validQueryData });
expect(grant.canRespondToAuthorizationRequest(request)).toBe(true);
});
it("returns false for missing client_id", async () => {
request = new OAuthRequest({
query: {
...validQueryData,
client_id: undefined,
},
});
expect(grant.canRespondToAuthorizationRequest(request)).toBe(false);
});
it("returns false when response_type !== code", async () => {
request = new OAuthRequest({
query: {
...validQueryData,
response_type: undefined,
},
});
expect(grant.canRespondToAuthorizationRequest(request)).toBe(false);
});
});
describe("validate authorization request", () => {
it("is successful with S256 pkce", async () => {
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
// single object arrays is valid
redirect_uri: ["http://example.com"],
state: "state-is-a-secret",
code_challenge: codeChallenge,
code_challenge_method: "S256",
},
});
const authorizationRequest = await grant.validateAuthorizationRequest(request);
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://example.com");
expect(authorizationRequest.state).toBe("state-is-a-secret");
expect(authorizationRequest.codeChallenge).toBe(codeChallenge);
expect(authorizationRequest.codeChallengeMethod).toBe("S256");
expect(authorizationRequest.scopes).toStrictEqual([]);
});
it("is successful with plain pkce", async () => {
client.redirectUris = ["http://example.com"];
inMemoryDatabase.clients[client.id] = client;
const plainCodeChallenge = "qqVDyvlSezXc64NY5Rx3BbLaT7c2xEBgoJP9domepFZLEjo9ln8EAaSdfewSNY5Rx3BbL";
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "http://example.com",
scope: "scope-1",
state: "state-is-a-secret",
code_challenge: base64urlencode(plainCodeChallenge), // code verifier plain
code_challenge_method: "plain",
},
});
const authorizationRequest = await grant.validateAuthorizationRequest(request);
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://example.com");
expect(authorizationRequest.state).toBe("state-is-a-secret");
expect(authorizationRequest.codeChallenge).toBe(base64urlencode(plainCodeChallenge));
expect(authorizationRequest.codeChallengeMethod).toBe("plain");
expect(authorizationRequest.scopes).toStrictEqual([{ name: "scope-1" }]);
});
it("is successful with request redirect uri with querystring", async () => {
client.redirectUris = ["http://example.com"];
inMemoryDatabase.clients[client.id] = client;
const plainCodeChallenge = "qqVDyvlSezXc64NY5Rx3BbLaT7c2xEBgoJP9domepFZLEjo9ln8EAaSdfewSNY5Rx3BbL";
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "http://example.com?this_should_work=true&also-this=yeah",
scope: "scope-1",
state: "state-is-a-secret",
code_challenge: base64urlencode(plainCodeChallenge), // code verifier plain
code_challenge_method: "plain",
},
});
const authorizationRequest = await grant.validateAuthorizationRequest(request);
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://example.com?this_should_work=true&also-this=yeah");
expect(authorizationRequest.state).toBe("state-is-a-secret");
expect(authorizationRequest.codeChallenge).toBe(base64urlencode(plainCodeChallenge));
expect(authorizationRequest.codeChallengeMethod).toBe("plain");
expect(authorizationRequest.scopes).toStrictEqual([{ name: "scope-1" }]);
});
it("is successful without using PKCE flow", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
scope: "scope-1",
state: "state-is-a-secret",
},
});
grant.options.requiresPKCE = false;
// act
const authorizationRequest = await grant.validateAuthorizationRequest(request);
// assert
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://example.com");
expect(authorizationRequest.state).toBe("state-is-a-secret");
expect(authorizationRequest.scopes).toStrictEqual([{ name: "scope-1" }]);
});
it("is successful with undefined redirect_uri", async () => {
const plainCodeChallenge = "qqVDyvlSezXc64NY5Rx3BbLaT7c2xEBgoJP9domepFZLEjo9ln8EAaSdfewSNY5Rx3BbL";
request = new OAuthRequest({
query: {
redirect_uri: undefined,
response_type: "code",
client_id: client.id,
code_challenge: base64urlencode(plainCodeChallenge), // code verifier plain
},
});
const authorizationRequest = await grant.validateAuthorizationRequest(request);
expect(authorizationRequest.redirectUri).toBe("http://example.com");
});
it("throws when missing code_challenge pkce", async () => {
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "http://example.com",
state: "state-is-a-secret",
code_challenge_method: "plain",
},
});
const authorizationRequest = grant.validateAuthorizationRequest(request);
await expect(authorizationRequest).rejects.toThrowError(
/The authorization server requires public clients to use PKCE RFC-7636/,
);
});
it.skip("throws for invalid code_challenge pkce format regex", async () => {
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "http://example.com",
state: "state-is-a-secret",
code_challenge: "invalid-format(with!Invalid~characters",
code_challenge_method: "S256",
},
});
const authorizationRequest = grant.validateAuthorizationRequest(request);
await expect(authorizationRequest).rejects.toThrowError(
/Code challenge must follow the specifications of RFC-7636 and match/,
);
});
it("throws for relative redirect_uri", async () => {
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "/foobydoo",
},
});
const authorizationRequest = grant.validateAuthorizationRequest(request);
await expect(authorizationRequest).rejects.toThrowError(/Check the `redirect_uri` parameter/);
});
it("throws for multiple redirect_uri args (array of strings)", async () => {
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: ["http://example.com", "http://example2.com"],
},
});
const authorizationRequest = grant.validateAuthorizationRequest(request);
await expect(authorizationRequest).rejects.toThrowError(/Check the `redirect_uri` parameter/);
});
it("throws for redirect_uri containing url fragment", async () => {
request = new OAuthRequest({
query: {
response_type: "code",
client_id: client.id,
redirect_uri: "http://example.com#fragle",
},
});
const authorizationRequest = grant.validateAuthorizationRequest(request);
await expect(authorizationRequest).rejects.toThrowError(
/Redirection endpoint must not contain url fragment based on RFC6749/,
);
});
});
describe("complete authorization request", () => {
it("is successful", async () => {
const authorizationRequest = new AuthorizationRequest("authorization_code", client, "http://example.com");
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.codeChallengeMethod = "S256";
authorizationRequest.codeChallenge = codeChallenge;
authorizationRequest.state = "abc123";
authorizationRequest.user = user;
const response = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(response.headers.location.split("?")[1]);
const decodedCode: IAuthCodePayload = <IAuthCodePayload>decode(String(authorizeResponseQuery.code));
expect(response.headers.location.includes("http://example.com?code=")).toBeTruthy();
expect(decodedCode.client_id).toBe(client.id);
expect(decodedCode.redirect_uri).toBe("http://example.com");
});
it("is successful with client with query", async () => {
client.redirectUris = ["http://example.com?this_should_work=true"];
inMemoryDatabase.clients[client.id] = client;
const authorizationRequest = new AuthorizationRequest(
"authorization_code",
client,
"http://example.com?this_should_work=true",
);
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.codeChallengeMethod = "S256";
authorizationRequest.codeChallenge = codeChallenge;
authorizationRequest.state = "abc123";
authorizationRequest.user = user;
const response = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(response.headers.location.split("?")[1]);
const decodedCode: IAuthCodePayload = <IAuthCodePayload>decode(String(authorizeResponseQuery.code));
expect(response.headers.location).toMatch(/http\:\/\/example\.com\?this_should_work=true\&code\=/);
expect(decodedCode.client_id).toBe(client.id);
expect(decodedCode.redirect_uri).toBe("http://example.com?this_should_work=true");
});
// it("uses clients redirect url if request ", async () => {});
it("is successful without pkce flow", async () => {
grant.options.requiresPKCE = false;
const authorizationRequest = new AuthorizationRequest("authorization_code", client, "http://example.com");
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.state = "abc123";
authorizationRequest.user = user;
const response = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(response.headers.location.split("?")[1]);
const decodedCode: IAuthCodePayload = <IAuthCodePayload>decode(String(authorizeResponseQuery.code));
expect(response.headers.location.includes("http://example.com?code=")).toBeTruthy();
expect(decodedCode.client_id).toBe(client.id);
expect(decodedCode.redirect_uri).toBe("http://example.com");
});
});
describe("respond to access token request with code", () => {
let authorizationRequest: AuthorizationRequest;
let authorizationCode: string;
beforeEach(async () => {
authorizationRequest = new AuthorizationRequest("authorization_code", client, "http://example.com");
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.codeChallengeMethod = "S256";
authorizationRequest.codeChallenge = codeChallenge;
authorizationRequest.user = user;
const redirectResponse = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(redirectResponse.headers.location.split("?")[1]);
authorizationCode = String(authorizeResponseQuery.code);
});
it("is successful with pkce S256", async () => {
// act
request = new OAuthRequest({
body: {
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: authorizationRequest.redirectUri,
client_id: client.id,
code_verifier: codeVerifier,
},
});
const accessTokenResponse = await grant.respondToAccessTokenRequest(request, new DateInterval("1h"));
// assert
expectTokenResponse(accessTokenResponse);
expect(accessTokenResponse.body.refresh_token).toMatch(REGEX_ACCESS_TOKEN);
});
it("is successful with pkce plain", async () => {
authorizationRequest = new AuthorizationRequest("authorization_code", client, "http://example.com");
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.codeChallengeMethod = "plain";
authorizationRequest.codeChallenge = codeChallenge;
authorizationRequest.user = user;
const redirectResponse = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(redirectResponse.headers.location.split("?")[1]);
authorizationCode = String(authorizeResponseQuery.code);
// act
request = new OAuthRequest({
body: {
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: authorizationRequest.redirectUri,
client_id: client.id,
code_verifier: codeChallenge,
},
});
const accessTokenResponse = await grant.respondToAccessTokenRequest(request, new DateInterval("1h"));
// assert
expectTokenResponse(accessTokenResponse);
expect(accessTokenResponse.body.refresh_token).toMatch(REGEX_ACCESS_TOKEN);
});
it("is successful without pkce", async () => {
grant.options.requiresPKCE = false;
authorizationRequest = new AuthorizationRequest("authorization_code", client, "http://example.com");
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.user = user;
const redirectResponse = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(redirectResponse.headers.location.split("?")[1]);
authorizationCode = String(authorizeResponseQuery.code);
// act
request = new OAuthRequest({
body: {
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: authorizationRequest.redirectUri,
client_id: client.id,
},
});
const accessTokenResponse = await grant.respondToAccessTokenRequest(request, new DateInterval("1h"));
// assert
expectTokenResponse(accessTokenResponse);
const decodedToken: any = decode(accessTokenResponse.body.access_token);
expect(decodedToken?.email).toBe("[email protected]");
expect(accessTokenResponse.body.refresh_token).toMatch(REGEX_ACCESS_TOKEN);
});
it("throws for confidential client when no secret is included in request", async () => {
client = {
...client,
secret: "auth-code-with-seccret",
};
inMemoryDatabase.clients[client.id] = client;
// act
request = new OAuthRequest({
body: {
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: authorizationRequest.redirectUri,
client_id: client.id,
code_verifier: codeVerifier + "invalid",
},
});
const accessTokenResponse = grant.respondToAccessTokenRequest(request, new DateInterval("1h"));
// assert
await expect(accessTokenResponse).rejects.toThrowError(/Client authentication failed/);
});
it("throws for invalid code_verifier format", async () => {
// act
request = new OAuthRequest({
body: {
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: authorizationRequest.redirectUri,
client_id: client.id,
code_verifier: "invalid",
},
});
const accessTokenResponse = grant.respondToAccessTokenRequest(request, new DateInterval("1h"));
// assert
await expect(accessTokenResponse).rejects.toThrowError(
/Code verifier must follow the specifications of RFS-7636/,
);
});
it("throws for incorrect code_verifier", async () => {
// act
request = new OAuthRequest({
body: {
grant_type: "authorization_code",
code: authorizationCode,
redirect_uri: authorizationRequest.redirectUri,
client_id: client.id,
code_verifier: codeVerifier + "broken",
},
});
const accessTokenResponse = grant.respondToAccessTokenRequest(request, new DateInterval("1h"));
// assert
await expect(accessTokenResponse).rejects.toThrowError(/Failed to verify code challenge/);
});
});
});
Example #9
Source File: implicit.grant.spec.ts From ts-oauth2-server with MIT License | 4 votes |
describe("implicit grant", () => {
let user: OAuthUser;
let client: OAuthClient;
let scope1: OAuthScope;
let scope2: OAuthScope;
let grant: ImplicitGrant;
let request: OAuthRequest;
beforeEach(() => {
request = new OAuthRequest();
user = {
id: "512ab9a4-c786-48a6-8ad6-94c53a8dc651",
password: "password123",
};
client = {
id: "35615f2f-13fa-4731-83a1-9e34556ab390",
name: "test client",
secret: "super-secret-secret",
redirectUris: ["http://example.com"],
allowedGrants: ["implicit"],
scopes: [],
};
scope1 = { name: "scope-1" };
scope2 = { name: "scope-2" };
grant = new ImplicitGrant(
inMemoryAuthCodeRepository,
inMemoryClientRepository,
inMemoryAccessTokenRepository,
inMemoryScopeRepository,
inMemoryUserRepository,
new JwtService("secret-key"),
);
inMemoryDatabase.clients[client.id] = client;
inMemoryDatabase.users[user.id] = user;
inMemoryDatabase.scopes[scope1.name] = scope1;
inMemoryDatabase.scopes[scope2.name] = scope2;
});
describe("validate authorization request", () => {
it("is successful with minimal request", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "token",
client_id: client.id,
redirect_uri: "http://example.com",
},
});
// act
const authorizationRequest = await grant.validateAuthorizationRequest(request);
// assert
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://example.com");
expect(authorizationRequest.state).toBeUndefined();
expect(authorizationRequest.codeChallenge).toBeUndefined();
expect(authorizationRequest.codeChallengeMethod).toBeUndefined();
expect(authorizationRequest.scopes).toStrictEqual([]);
});
it("is successful with state and scopes", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "token",
client_id: client.id,
redirect_uri: "http://example.com",
state: "f2ae4dc5-b535-4949-aaed-54ebbf08e876",
scope: "scope-1 scope-2",
},
});
// act
const authorizationRequest = await grant.validateAuthorizationRequest(request);
// assert
expect(authorizationRequest.isAuthorizationApproved).toBe(false);
expect(authorizationRequest.client.id).toBe(client.id);
expect(authorizationRequest.client.name).toBe(client.name);
expect(authorizationRequest.redirectUri).toBe("http://example.com");
expect(authorizationRequest.state).toBe("f2ae4dc5-b535-4949-aaed-54ebbf08e876");
expect(authorizationRequest.codeChallenge).toBeUndefined();
expect(authorizationRequest.codeChallengeMethod).toBeUndefined();
expect(authorizationRequest.scopes).toStrictEqual([scope1, scope2]);
});
it("throws if missing client_id", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "token",
},
});
// act
const authorizationRequest = grant.validateAuthorizationRequest(request);
// assert
await expect(authorizationRequest).rejects.toThrowError(/Check the `client_id` parameter/);
});
it("throws if missing redirect_uri", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "token",
client_id: client.id,
},
});
// act
const authorizationRequest = await grant.validateAuthorizationRequest(request);
// assert
expect(authorizationRequest.redirectUri).toBe("http://example.com");
});
it("throws when passed invalid scopes", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "token",
client_id: client.id,
redirect_uri: "http://example.com",
scope: "scope-1 non-existant non-existant-2",
},
});
// act
const authorizationRequest = grant.validateAuthorizationRequest(request);
// assert
await expect(authorizationRequest).rejects.toThrowError(/Check the `non-existant, non-existant-2` scope\(s\)/);
});
});
describe("complete authorization request", () => {
it("is successful", async () => {
// arrange
const now = roundToSeconds(Date.now());
const authorizationRequest = new AuthorizationRequest("implicit", client, "http://example.com");
authorizationRequest.user = user;
authorizationRequest.isAuthorizationApproved = true;
authorizationRequest.state = "abc123-state";
// act
const response = await grant.completeAuthorizationRequest(authorizationRequest);
const authorizeResponseQuery = querystring.parse(response.headers.location.split("?")[1]);
const decodedCode = <ITokenData>decode(String(authorizeResponseQuery.access_token));
// assert
expect(authorizeResponseQuery.state).toBe("abc123-state");
expect(decodedCode.sub).toBe(user.id);
expect(decodedCode.jti).toMatch(REGEX_ACCESS_TOKEN);
expect(decodedCode.exp).toBeGreaterThan(now);
expect(decodedCode.iat).toBe(now);
});
it("will not complete if isAuthorizationApproved=false", async () => {
// arrange
const authorizationRequest = new AuthorizationRequest("implicit", client, "http://example.com");
authorizationRequest.user = user;
authorizationRequest.isAuthorizationApproved = false;
// act
const response = grant.completeAuthorizationRequest(authorizationRequest);
//assert
await expect(response).rejects.toThrowError(/The resource owner or authorization server denied the request/);
});
// it("uses clients redirect url if request ", async () => {});
});
describe("canRespondToAccessTokenRequest", () => {
it("valid request can respond", async () => {
// arrange
request = new OAuthRequest({
query: {
response_type: "token",
client_id: client.id,
},
});
// act
const canRespond = grant.canRespondToAuthorizationRequest(request);
// assert
expect(canRespond).toBeTruthy();
});
it("invalid request cannot respond", async () => {
// arrange
request = new OAuthRequest({ query: {} });
// assert
expect(grant.canRespondToAuthorizationRequest(request)).toBeFalsy();
expect(grant.canRespondToAccessTokenRequest(request)).toBeFalsy();
});
});
describe("respondToAccessTokenRequest", () => {
it("throws because implicit grant cannot respond to access token requests", async () => {
// assert
expect(() => grant.respondToAccessTokenRequest(request, new DateInterval("1h"))).toThrowError(
/The implicit grant can't respond to access token requests/,
);
});
});
});
Example #10
Source File: sep10.ts From stellar-anchor-tests with Apache License 2.0 | 4 votes |
export async function postChallenge(
clientKeypair: Keypair,
webAuthEndpoint: string,
networkPassphrase: string,
result: Result,
useJson: boolean = false,
challenge?: Transaction,
): Promise<string | void> {
if (!challenge) {
challenge = (await getChallenge(
clientKeypair,
webAuthEndpoint,
networkPassphrase,
result,
)) as Transaction;
if (!challenge) return;
challenge.sign(clientKeypair);
}
let request: Request;
if (useJson) {
request = new Request(webAuthEndpoint, {
method: "POST",
body: JSON.stringify({ transaction: challenge.toXDR() }),
headers: { "Content-Type": "application/json" },
});
} else {
request = new Request(webAuthEndpoint, {
method: "POST",
body: `transaction=${encodeURIComponent(challenge.toXDR())}`,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
});
}
const postAuthCall: NetworkCall = { request: request };
result.networkCalls.push(postAuthCall);
try {
postAuthCall.response = await fetch(postAuthCall.request.clone());
} catch {
result.failure = makeFailure(postChallengeFailureModes.CONNECTION_ERROR, {
url: postAuthCall.request.url,
});
return;
}
if (postAuthCall.response.status !== 200) {
result.failure = makeFailure(
postChallengeFailureModes.UNEXPECTED_STATUS_CODE,
);
result.expected = 200;
result.actual = postAuthCall.response.status;
return;
}
const postAuthResponseContentType =
postAuthCall.response.headers.get("Content-Type");
if (
!postAuthResponseContentType ||
!postAuthResponseContentType.includes("application/json")
) {
result.failure = makeFailure(postChallengeFailureModes.BAD_CONTENT_TYPE);
result.expected = "application/json";
if (postAuthResponseContentType)
result.actual = postAuthResponseContentType;
return;
}
const responseBody = await postAuthCall.response.clone().json();
if (!responseBody.token) {
result.failure = makeFailure(postChallengeFailureModes.NO_TOKEN);
return;
}
let jwtContents;
try {
jwtContents = decode(responseBody.token);
} catch (e) {
result.failure = makeFailure(postChallengeFailureModes.JWT_DECODE_FAILURE, {
error: e.message,
});
return;
}
if (!jwtContents || typeof jwtContents !== "object") {
result.failure = makeFailure(postChallengeFailureModes.JWT_NOT_JSON);
return;
}
const validatorResult = validate(jwtContents, jwtSchema);
if (validatorResult.errors.length !== 0) {
result.failure = makeFailure(postChallengeFailureModes.INVALID_JWT_SCHEMA, {
errors: validatorResult.errors.join("\n"),
});
return;
}
try {
Keypair.fromPublicKey(jwtContents.sub);
} catch {
result.failure = makeFailure(postChallengeFailureModes.INVALID_JWT_SUB);
return;
}
return responseBody.token;
}