Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FI-2857: Add auth input option #514

Merged
merged 34 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
bcd98d2
add single checkbox option
AlyssaWang Jun 28, 2024
6472811
clean up input types
AlyssaWang Jul 2, 2024
777a0eb
modularize auth settings
AlyssaWang Jul 5, 2024
a6524fd
fix default selection value
AlyssaWang Jul 5, 2024
0c0e52e
update auth field handling
AlyssaWang Jul 6, 2024
a7266d5
Merge branch 'main' of github.com:inferno-framework/inferno-core into…
AlyssaWang Jul 6, 2024
70faaba
add access components
AlyssaWang Jul 6, 2024
201d913
fix heading increase
AlyssaWang Jul 6, 2024
5228cf5
revise default value handling
AlyssaWang Jul 8, 2024
2a13cec
format radio button inputs
AlyssaWang Jul 8, 2024
d11dd65
fix default checkbox bug
AlyssaWang Jul 8, 2024
678f006
update default values for auth
AlyssaWang Jul 8, 2024
5f8455f
fix serialization for auth
AlyssaWang Jul 8, 2024
4e8e43e
clean up access inputs
AlyssaWang Jul 9, 2024
0748e02
disable required checks
AlyssaWang Jul 9, 2024
3a10163
revert lock file
AlyssaWang Jul 9, 2024
d31e592
add case for handling auth info required fields
AlyssaWang Jul 9, 2024
d9ea1a0
Merge branch 'main' of github.com:inferno-framework/inferno-core into…
AlyssaWang Jul 30, 2024
9791f08
Merge branch 'main' of github.com:inferno-framework/inferno-core into…
AlyssaWang Jul 31, 2024
edd312e
add dropdown to access mode and auth_type to request
AlyssaWang Aug 1, 2024
ceb4897
factor out auth type dropdown
AlyssaWang Aug 1, 2024
4ecfc2d
add support for modifying auth type
AlyssaWang Aug 1, 2024
c699e9a
normalize values
AlyssaWang Aug 5, 2024
71a877a
add parsing for prepopulated values
AlyssaWang Aug 5, 2024
7d1e018
add handling for required inputs when auth type change
AlyssaWang Aug 5, 2024
4cf5b2e
remove logs
AlyssaWang Aug 5, 2024
30d9af3
update test
AlyssaWang Aug 5, 2024
a521401
add auth type change handling to access
AlyssaWang Aug 7, 2024
7214842
trigger data change in radio buttons
AlyssaWang Aug 7, 2024
ae5b8ba
update radio defaults
AlyssaWang Aug 7, 2024
92043b4
unify auth and access modes
AlyssaWang Aug 8, 2024
07c7add
revert access hidden fields
AlyssaWang Aug 8, 2024
cd2abb0
reenable locked behavior
AlyssaWang Aug 9, 2024
3a55d12
update hide/show requirements for backend services
AlyssaWang Aug 20, 2024
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
350 changes: 350 additions & 0 deletions client/src/components/InputsModal/AuthSettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,350 @@
import { TestInput } from '~/models/testSuiteModels';

export type AuthType = 'public' | 'symmetric' | 'asymmetric' | 'backend_services';

export const authSettings = {
public: [
'use_discovery',
'client_id',
'requested_scopes',
'pkce_support',
'pkce_code_challenge_method',
'auth_request_method',
'auth_url',
'token_url',
],
symmetric: [
'use_discovery',
'client_id',
'client_secret',
'requested_scopes',
'pkce_support',
'pkce_code_challenge_method',
'auth_request_method',
'auth_url',
'token_url',
],
asymmetric: [
'use_discovery',
'client_id',
'requested_scopes',
'pkce_support',
'pkce_code_challenge_method',
'auth_request_method',
'encryption_algorithm',
'jwks',
'kid',
'auth_url',
'token_url',
],
backend_services: [
'use_discovery',
'client_id',
'requested_scopes',
'encryption_algorithm',
'jwks',
'kid',
'token_url',
],
};

export const getAuthFields = (
authType: AuthType,
authValues: Map<string, unknown>,
components: TestInput[]
): TestInput[] => {
const fields = [
{
name: 'use_discovery',
type: 'checkbox',
title: 'Populate fields from discovery',
optional: true,
default: 'true',
},
{
name: 'auth_url',
title: 'Authorization URL',
description: "URL of the server's authorization endpoint",
optional: true,
hide: authValues?.get('use_discovery') === 'true',
},
{
name: 'token_url',
title: 'Token URL',
description: "URL of the authorization server's token endpoint",
optional: true,
hide: authValues?.get('use_discovery') === 'true',
},
{
name: 'requested_scopes',
title: 'Scopes',
description: 'OAuth 2.0 scopes needed to enable all required functionality',
},
{
name: 'client_id',
title: 'Client ID',
description: 'Client ID provided during registration of Inferno',
},
{
name: 'client_secret',
title: 'Client Secret',
description: 'Client secret provided during registration of Inferno',
},
{
name: 'pkce_support',
type: 'radio',
title: 'Proof Key for Code Exchange (PKCE)',
options: {
list_options: [
{
label: 'Enabled',
value: 'enabled',
},
{
label: 'Disabled',
value: 'disabled',
},
],
},
},
{
name: 'pkce_code_challenge_method',
type: 'radio',
title: 'PKCE Code Challenge Method',
optional: true,
options: {
list_options: [
{
label: 'S256',
value: 'S256',
},
{
label: 'Plain',
value: 'plain',
},
],
},
hide: authValues ? authValues.get('pkce_support') === 'disabled' : false,
},
{
name: 'auth_request_method',
type: 'radio',
title: 'Authorization Request Method',
options: {
list_options: [
{
label: 'GET',
value: 'GET',
},
{
label: 'POST',
value: 'POST',
},
],
},
},
{
name: 'encryption_algorithm',
type: 'radio',
title: 'Encryption Algorithm',
options: {
list_options: [
{
label: 'ES384',
value: 'ES384',
},
{
label: 'RS384',
value: 'RS384',
},
],
},
},
{
name: 'kid',
title: 'Key ID (kid)',
description:
'Key ID of the JWKS private key used to sign the client assertion. If blank, the first key for the selected encryption algorithm will be used.',
optional: true,
},
{
name: 'jwks',
type: 'textarea',
title: 'JWKS',
description:
"The JWKS (including private keys) which will be used to sign the client assertion. If blank, Inferno's default JWKS will be used.",
optional: true,
},
] as TestInput[];

// If the requirement contains custom fields, replace default fields
const fieldsToUpdate = components.map((component) => component.name);
fields.forEach((field, i) => {
if (fieldsToUpdate.includes(field.name)) {
const customComponent = components.find((component) => component.name === field.name);
fields[i] = { ...field, ...customComponent };
}
});

// Remove extra properties based on auth type or hide if no settings
const typeValues = authSettings[authType];
if (authSettings && authType) {
return fields.filter((field) => typeValues.includes(field.name));
}
fields.forEach((field) => (field.hide = field.hide || !typeValues.includes(field.name)));
return fields;
};

export const accessSettings = {
public: ['access_token', 'refresh_token', 'client_id', 'token_url', 'issue_time', 'expires_in'],
symmetric: [
'access_token',
'refresh_token',
'client_id',
'client_secret',
'token_url',
'issue_time',
'expires_in',
],
asymmetric: [
'access_token',
'refresh_token',
'client_id',
'token_url',
'encryption_algorithm',
'jwks',
'kid',
'issue_time',
'expires_in',
],
backend_services: [
'access_token',
'client_id',
'token_url',
'encryption_algorithm',
'jwks',
'kid',
'issue_time',
'expires_in',
],
};

export const getAccessFields = (
authType: AuthType,
accessValues: Map<string, unknown>,
components: TestInput[]
): TestInput[] => {
const fields = [
{
name: 'access_token',
title: 'Access Token',
},
{
name: 'refresh_token',
title: 'Refresh Token (will automatically refresh if available)',
optional: true,
},
{
name: 'client_id',
title: 'Client ID',
description: 'Client ID provided during registration of Inferno',
optional: true,
hide: !accessValues.get('refresh_token'),
},
{
name: 'client_secret',
title: 'Client Secret',
description: 'Client secret provided during registration of Inferno',
optional: true,
hide: !accessValues.get('refresh_token'),
},
{
name: 'token_url',
title: 'Token URL',
description: "URL of the authorization server's token endpoint",
optional: true,
hide: !accessValues.get('refresh_token'),
},
{
name: 'encryption_algorithm',
type: 'radio',
title: 'Encryption Algorithm',
options: {
list_options: [
{
label: 'ES384',
value: 'ES384',
},
{
label: 'RS384',
value: 'RS384',
},
],
},
optional: true,
hide:
!accessValues.get('refresh_token') ||
(authType === 'backend_services' && !accessValues.get('access_token')),
},
{
name: 'kid',
title: 'Key ID (kid)',
description:
'Key ID of the JWKS private key used to sign the client assertion. If blank, the first key for the selected encryption algorithm will be used.',
optional: true,
hide:
authType === 'backend_services'
? !accessValues.get('access_token')
: !accessValues.get('refresh_token'),
},
{
name: 'jwks',
type: 'textarea',
title: 'JWKS',
description:
"The JWKS (including private keys) which will be used to sign the client assertion. If blank, Inferno's default JWKS will be used.",
optional: true,
hide:
authType === 'backend_services'
? !accessValues.get('access_token')
: !accessValues.get('refresh_token'),
},
{
name: 'issue_time',
title: 'Access Token Issue Time',
description: 'The time that the access token was issued in iso8601 format',
optional: true,
hide:
authType === 'backend_services'
? !accessValues.get('access_token')
: !accessValues.get('refresh_token'),
},
{
name: 'expires_in',
title: 'Token Lifetime',
description: 'The lifetime of the access token in seconds',
optional: true,
hide:
authType === 'backend_services'
? !accessValues.get('access_token')
: !accessValues.get('refresh_token'),
},
] as TestInput[];

// If the requirement contains custom fields, replace default fields
const fieldsToUpdate = components.map((component) => component.name);
fields.forEach((field, i) => {
if (fieldsToUpdate.includes(field.name)) {
const customComponent = components.find((component) => component.name === field.name);
fields[i] = { ...field, ...customComponent };
}
});

// Remove extra properties based on auth type or hide if no settings
const typeValues = accessSettings[authType];
if (accessSettings && authType) {
return fields.filter((field) => typeValues.includes(field.name));
}
fields.forEach((field) => (field.hide = field.hide || !typeValues.includes(field.name)));
return fields;
};
Loading
Loading