Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
9f6141b
feat: riskAssessments integration
josh-cain Nov 24, 2025
2bf229d
feedback: nest new device settings under riskAssessment
josh-cain Dec 4, 2025
659aed8
Merge branch 'master' into addRiskAssessmentConfig
josh-cain Dec 4, 2025
9f11f9d
Merge branch 'master' into addRiskAssessmentConfig
josh-cain Dec 5, 2025
a3145bc
feedbadck: null check for status code
josh-cain Dec 5, 2025
8b30faf
feedback: remove useless catch
josh-cain Dec 5, 2025
98b09de
remove additional references to previous/legacy format
josh-cain Dec 5, 2025
c83d43f
null checkery
josh-cain Dec 5, 2025
318b968
shorthand
josh-cain Dec 5, 2025
6818cb8
feedback: singular-ize riskAssessments
josh-cain Dec 8, 2025
3e38f5c
Update docs/resource-specific-documentation.md
josh-cain Dec 12, 2025
c73ad14
Update src/tools/constants.ts
josh-cain Dec 12, 2025
6c9931a
feedback: more renaming
josh-cain Dec 12, 2025
b64421f
fix: tests should reflect singular naming too
josh-cain Dec 12, 2025
11b651b
Merge branch 'master' into addRiskAssessmentConfig
kushalshit27 Dec 14, 2025
863a41e
Merge branch 'master' into addRiskAssessmentConfig
kushalshit27 Dec 20, 2025
cf25eea
feat: update risk assessment schema structure
kushalshit27 Dec 20, 2025
3c7b539
feat: update risk assessment structure and tests
kushalshit27 Dec 20, 2025
63a5f2d
feat: update risk assessment configuration and examples
kushalshit27 Dec 20, 2025
bb528f1
update e2e
kushalshit27 Dec 21, 2025
168018a
feat: update risk assessment types and remove settings.json
kushalshit27 Dec 21, 2025
592fc28
update e2e
kushalshit27 Dec 21, 2025
fcf3bbb
update e2e
kushalshit27 Dec 21, 2025
9b5f240
E2E add cross_origin_authentication to client configurations test-data
kushalshit27 Dec 21, 2025
53ce517
E2E updated
kushalshit27 Dec 21, 2025
9206aa6
E2E:enable cross_origin_authentication for Deploy CLI client on test-…
kushalshit27 Dec 21, 2025
c499cb0
e2e update
kushalshit27 Dec 22, 2025
4422674
e2e update
kushalshit27 Dec 22, 2025
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
24 changes: 24 additions & 0 deletions docs/resource-specific-documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,30 @@ phoneProviders:
]
```

## Risk Assessments

Risk assessments configuration allows you to enable or disable risk assessment features for your tenant.

### YAML Example

```yaml
# Contents of ./tenant.yaml
riskAssessment:
enabled: true
```

### Directory Example

File: `./risk-assessments/settings.json`

```json
{
"enabled": true
}
```

For more details, see the [Management API documentation](https://auth0.com/docs/api/management/v2#!/Risk_Assessments/get_settings).

## Connection Profiles

Application specific configuration for use with the OIN Express Configuration feature
Expand Down
3 changes: 3 additions & 0 deletions examples/directory/risk-assessments/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"enabled": false
}
5 changes: 5 additions & 0 deletions examples/yaml/tenant.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -419,3 +419,8 @@ userAttributeProfiles:
type: "email"
required: true

riskAssessment:
enabled: false
# newDevice:
# remember_for: 30

2 changes: 2 additions & 0 deletions src/context/directory/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import actions from './actions';
import organizations from './organizations';
import triggers from './triggers';
import attackProtection from './attackProtection';
import riskAssessments from './riskAssessments';
import branding from './branding';
import phoneProviders from './phoneProvider';
import logStreams from './logStreams';
Expand Down Expand Up @@ -69,6 +70,7 @@ const directoryHandlers: {
organizations,
triggers,
attackProtection,
riskAssessment: riskAssessments,
branding,
phoneProviders,
logStreams,
Expand Down
56 changes: 56 additions & 0 deletions src/context/directory/handlers/riskAssessments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import path from 'path';
import fs from 'fs-extra';
import { constants } from '../../../tools';
import { dumpJSON, existsMustBeDir, isFile, loadJSON } from '../../../utils';
import { DirectoryHandler } from '.';
import DirectoryContext from '..';
import { ParsedAsset, Asset } from '../../../types';

type ParsedRiskAssessment = ParsedAsset<'riskAssessment', Asset>;

function parse(context: DirectoryContext): ParsedRiskAssessment {
const riskAssessmentsDirectory = path.join(
context.filePath,
constants.RISK_ASSESSMENTS_DIRECTORY
);
const riskAssessmentsFile = path.join(riskAssessmentsDirectory, 'settings.json');

if (!existsMustBeDir(riskAssessmentsDirectory)) {
return { riskAssessment: null };
}

if (!isFile(riskAssessmentsFile)) {
return { riskAssessment: null };
}

const riskAssessment = loadJSON(riskAssessmentsFile, {
mappings: context.mappings,
disableKeywordReplacement: context.disableKeywordReplacement,
});

return {
riskAssessment,
};
}

async function dump(context: DirectoryContext): Promise<void> {
const { riskAssessment } = context.assets;

if (!riskAssessment) return;

const riskAssessmentsDirectory = path.join(
context.filePath,
constants.RISK_ASSESSMENTS_DIRECTORY
);
const riskAssessmentsFile = path.join(riskAssessmentsDirectory, 'settings.json');

fs.ensureDirSync(riskAssessmentsDirectory);
dumpJSON(riskAssessmentsFile, riskAssessment);
}

const riskAssessmentsHandler: DirectoryHandler<ParsedRiskAssessment> = {
parse,
dump,
};

export default riskAssessmentsHandler;
2 changes: 2 additions & 0 deletions src/context/yaml/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import organizations from './organizations';
import actions from './actions';
import triggers from './triggers';
import attackProtection from './attackProtection';
import riskAssessments from './riskAssessments';
import branding from './branding';
import phoneProviders from './phoneProvider';
import logStreams from './logStreams';
Expand Down Expand Up @@ -67,6 +68,7 @@ const yamlHandlers: { [key in AssetTypes]: YAMLHandler<{ [key: string]: unknown
organizations,
triggers,
attackProtection,
riskAssessment: riskAssessments,
branding,
phoneProviders,
logStreams,
Expand Down
32 changes: 32 additions & 0 deletions src/context/yaml/handlers/riskAssessments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { YAMLHandler } from '.';
import YAMLContext from '..';
import { Asset, ParsedAsset } from '../../../types';

type ParsedRiskAssessment = ParsedAsset<'riskAssessment', Asset>;

async function parse(context: YAMLContext): Promise<ParsedRiskAssessment> {
const { riskAssessment } = context.assets;

if (!riskAssessment) return { riskAssessment: null };

return {
riskAssessment,
};
}

async function dump(context: YAMLContext): Promise<ParsedRiskAssessment> {
const { riskAssessment } = context.assets;

if (!riskAssessment) return { riskAssessment: null };

return {
riskAssessment,
};
}

const riskAssessmentsHandler: YAMLHandler<ParsedRiskAssessment> = {
parse,
dump,
};

export default riskAssessmentsHandler;
2 changes: 2 additions & 0 deletions src/tools/auth0/handlers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import * as actions from './actions';
import * as triggers from './triggers';
import * as organizations from './organizations';
import * as attackProtection from './attackProtection';
import * as riskAssessments from './riskAssessments';
import * as logStreams from './logStreams';
import * as customDomains from './customDomains';
import * as themes from './themes';
Expand Down Expand Up @@ -66,6 +67,7 @@ const auth0ApiHandlers: { [key in AssetTypes]: any } = {
triggers,
organizations,
attackProtection,
riskAssessment: riskAssessments,
logStreams,
customDomains,
themes,
Expand Down
99 changes: 99 additions & 0 deletions src/tools/auth0/handlers/riskAssessments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import DefaultAPIHandler from './default';
import { Assets } from '../../../types';

export const schema = {
type: 'object',
properties: {
enabled: {
type: 'boolean',
description: 'Whether or not risk assessment is enabled.',
},
newDevice: {
type: 'object',
properties: {
remember_for: {
type: 'number',
description: 'Length of time to remember devices for, in days.',
},
},
required: ['remember_for'],
},
},
required: ['enabled'],
};

export type RiskAssessmentsSettings = {
enabled: boolean;
newDevice?: {
remember_for: number;
};
};

export default class RiskAssessmentsHandler extends DefaultAPIHandler {
existing: RiskAssessmentsSettings | null;

constructor(config: DefaultAPIHandler) {
super({
...config,
type: 'riskAssessment',
});
}

async getType(): Promise<RiskAssessmentsSettings> {
if (this.existing) {
return this.existing;
}

try {
const [settings, newDeviceSettings] = await Promise.all([
this.client.riskAssessments.getSettings(),
this.client.riskAssessments.getNewDeviceSettings().catch((err) => {
if (err?.statusCode === 404) return { data: { remember_for: 0 } };
throw err;
}),
]);

this.existing = {
enabled: settings.data.enabled,
...(newDeviceSettings.data.remember_for > 0 && {
newDevice: {
remember_for: newDeviceSettings.data.remember_for,
},
}),
};
return this.existing;
} catch (err) {
if (err.statusCode === 404) return { enabled: false };
throw err;
}
}

async processChanges(assets: Assets): Promise<void> {
const { riskAssessment } = assets;

// Non-existing section means it doesn't need to be processed
if (!riskAssessment) {
return;
}

const updates: Promise<unknown>[] = [];

// Update main settings (enabled flag)
const settings = {
enabled: riskAssessment.enabled as boolean,
};
updates.push(this.client.riskAssessments.updateSettings(settings));

// Update new device settings if provided
if (riskAssessment.newDevice) {
const newDeviceSettings = {
remember_for: riskAssessment.newDevice.remember_for as number,
};
updates.push(this.client.riskAssessments.updateNewDeviceSettings(newDeviceSettings));
}

await Promise.all(updates);
this.updated += 1;
this.didUpdate(riskAssessment);
}
}
1 change: 1 addition & 0 deletions src/tools/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ const constants = {
CONNECTIONS_ID_NAME: 'id',
ROLES_DIRECTORY: 'roles',
ATTACK_PROTECTION_DIRECTORY: 'attack-protection',
RISK_ASSESSMENTS_DIRECTORY: 'risk-assessments',
GUARDIAN_FACTORS: [
'sms',
'push-notification',
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export type Asset = { [key: string]: any };
export type Assets = Partial<{
actions: Action[] | null;
attackProtection: AttackProtection | null;
riskAssessment: Asset | null;
branding:
| (Asset & {
templates?: { template: string; body: string }[] | null;
Expand Down Expand Up @@ -178,6 +179,7 @@ export type AssetTypes =
| 'organizations'
| 'triggers'
| 'attackProtection'
| 'riskAssessment'
| 'branding'
| 'phoneProviders'
| 'logStreams'
Expand Down
Loading