Skip to content

Commit

Permalink
ApiResource serialization bug (#34)
Browse files Browse the repository at this point in the history
* ApiResource configuration serialization bug fixed

* Tests added
  • Loading branch information
AleF83 authored Aug 10, 2020
1 parent 2c190f5 commit b639fe9
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 39 deletions.
1 change: 1 addition & 0 deletions e2e/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
OIDC_TOKEN_URL=http://localhost:8080/connect/token
OIDC_AUTHORIZE_URL=http://localhost:8080/connect/authorize
OIDC_INTROSPECTION_URL=http://localhost:8080/connect/introspect
5 changes: 3 additions & 2 deletions e2e/config/api-resources.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[
{
"Name": "some-app",
"Scopes": ["some-app-scope-1", "some-app-scope-2"]
"Scopes": ["some-app-scope-1", "some-app-scope-2"],
"ApiSecrets": ["some-app-secret-1"]
}
]
]
7 changes: 7 additions & 0 deletions e2e/config/clients-configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,12 @@
"ValueType": "json"
}
]
},
{
"ClientId": "introspect-client-id",
"ClientSecrets": ["introspect-client-secret"],
"Description": "Client for introspect endpoint test",
"AllowedGrantTypes": ["client_credentials"],
"AllowedScopes": ["some-app-scope-1"]
}
]
12 changes: 8 additions & 4 deletions e2e/jest.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,21 @@
"displayName": "Backend Tests",
"preset": "ts-jest",
"rootDir": ".",
"snapshotSerializers": ["<rootDir>/utils/jwt-serializer.js"],
"snapshotSerializers": ["<rootDir>/utils/jwt-serializer.js", "<rootDir>/utils/jwt-payload-serializer.js"],
"testTimeout": 60000,
"testMatch": ["<rootDir>/tests/**/*.spec.ts"],
"testPathIgnorePatterns": ["<rootDir>/node_modules/", "<rootDir>/dist/", "<rootDir>/tests/authorization-endpoint.spec.ts"],
"testPathIgnorePatterns": [
"<rootDir>/node_modules/",
"<rootDir>/dist/",
"<rootDir>/tests/authorization-endpoint.spec.ts"
],
"runner": "<rootDir>/utils/backend-test-runner.js"
},
{
"displayName": "Frontend Tests",
"preset": "jest-playwright-preset",
"rootDir": ".",
"snapshotSerializers": ["<rootDir>/utils/jwt-serializer.js"],
"snapshotSerializers": ["<rootDir>/utils/jwt-serializer.js", "<rootDir>/utils/jwt-payload-serializer.js"],
"testTimeout": 60000,
"testMatch": ["<rootDir>/tests/**/authorization-endpoint.spec.ts"],
"testPathIgnorePatterns": ["<rootDir>/node_modules/", "<rootDir>/dist/"],
Expand All @@ -24,4 +28,4 @@
"runner": "<rootDir>/utils/frontend-test-runner.js"
}
]
}
}
17 changes: 17 additions & 0 deletions e2e/tests/__snapshots__/introspection-endpoint.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Introspection Endpoint Unknown token 1`] = `
Object {
"active": false,
}
`;

exports[`Introspection Endpoint Valid token 1`] = `
{
"iss": "http://localhost:8080",
"aud": "some-app",
"client_id": "introspect-client-id",
"active": true,
"scope": "some-app-scope-1"
}
`;
81 changes: 81 additions & 0 deletions e2e/tests/introspection-endpoint.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as querystring from 'querystring';
import * as dotenv from 'dotenv';
import axios, { AxiosRequestConfig } from 'axios';

import { sign } from 'jws';
import apiResources from '../config/api-resources.json';
import clients from '../config/clients-configuration.json';
import type { ApiResource, Client } from '../types';

const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

describe('Introspection Endpoint', () => {
let apiResource: ApiResource;
let requestConfig: AxiosRequestConfig;

beforeAll(() => {
dotenv.config();
apiResource = apiResources.find(aR => aR.Name === 'some-app');
expect(apiResource).toBeDefined();
const auth = btoa(`${apiResource.Name}:${apiResource.ApiSecrets?.[0]}`);
requestConfig = {
headers: {
Authorization: `Basic ${auth}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
};
});

test('Valid token', async () => {
const client: Client = clients.find(c => c.ClientId === 'introspect-client-id');
expect(client).toBeDefined();

const parameters = {
client_id: client.ClientId,
client_secret: client.ClientSecrets?.[0],
grant_type: 'client_credentials',
scope: client.AllowedScopes[0],
};

const tokenResponse = await axios.post(process.env.OIDC_TOKEN_URL, querystring.stringify(parameters));

expect(tokenResponse).toBeDefined();
const token = tokenResponse.data.access_token;
expect(token).toBeDefined();
const requestBody = querystring.stringify({
token,
});

const response = await axios.post(process.env.OIDC_INTROSPECTION_URL, requestBody, requestConfig);

expect(response).toBeDefined();
expect(response.data).toMatchSnapshot();
});

test('Unknown token', async () => {
const requestBody = querystring.stringify({
token: sign({
header: {
alg: 'HS256',
typ: 'JWT',
},
payload: {
nbf: 1597042883,
exp: 1597042884,
iss: 'http://localhost:8080',
aud: 'some-app',
client_id: 'introspect-client-id',
jti: '96E474ECF2D289741861976143C2BF54',
iat: 1597042883,
scope: ['some-app-scope-1'],
},
secret: 'very-strong-secret',
}),
});

const response = await axios.post(process.env.OIDC_INTROSPECTION_URL, requestBody, requestConfig);

expect(response).toBeDefined();
expect(response.data).toMatchSnapshot();
});
});
5 changes: 5 additions & 0 deletions e2e/types/api-resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default interface ApiResource {
Name: string;
Scopes?: string[];
ApiSecrets?: string[];
}
3 changes: 2 additions & 1 deletion e2e/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Claim from './claim';
import ApiResource from './api-resource';
import Client from './client';
import User from './user';

export { Claim, Client, User };
export { ApiResource, Claim, Client, User };
9 changes: 9 additions & 0 deletions e2e/utils/jwt-payload-serializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
test(arg) {
return arg.iat && arg.exp && arg.nbf;
},
print(val) {
const { exp, iat, jti, nbf, auth_time, sid, at_hash, ...payload } = val;
return JSON.stringify(payload, undefined, 2);
},
};
8 changes: 4 additions & 4 deletions src/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public static IEnumerable<ApiResource> GetApiResources()
}
apiResourcesStr = File.ReadAllText(apiResourcesFilePath);
}
var apiResourceNames = JsonConvert.DeserializeObject<IEnumerable<ApiResource>>(apiResourcesStr, new ApiResourceJsonConverter());
return apiResourceNames;
var apiResources = JsonConvert.DeserializeObject<IEnumerable<ApiResource>>(apiResourcesStr, new SecretConverter(), new ClaimJsonConverter());
return apiResources;
}

public static IEnumerable<Client> GetClients()
Expand Down Expand Up @@ -115,8 +115,8 @@ private static IEnumerable<IdentityResource> GetCustomIdentityResources()
identityResourcesStr = File.ReadAllText(identityResourcesFilePath);
}

var identityResourceConifgs = JsonConvert.DeserializeObject<IdentityResourceConfig[]>(identityResourcesStr);
return identityResourceConifgs.Select(c => new IdentityResource(c.Name, c.ClaimTypes));
var identityResourceConfig = JsonConvert.DeserializeObject<IdentityResourceConfig[]>(identityResourcesStr);
return identityResourceConfig.Select(c => new IdentityResource(c.Name, c.ClaimTypes));
}

private class IdentityResourceConfig
Expand Down
28 changes: 0 additions & 28 deletions src/utils/ApiResourceJsonConverter.cs

This file was deleted.

0 comments on commit b639fe9

Please sign in to comment.