Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -285,5 +285,8 @@ temp-cache.json
# Jest JUnit reporter
junit.xml

# MSAL Native Auth config files (contains sensitive data)
samples/msal-browser-samples/NativeAuthSample/nativeAuthConfig.json

# ApiExtractor
temp/
temp/
1 change: 1 addition & 0 deletions .pipelines/3p-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ extends:
- "pop"
- "customizable-e2e-test"
- "ExpressSample"
- "NativeAuthSample"
debug: ${{ parameters.debug }}
npmInstallTimeout: ${{ parameters.npmInstallTimeout }}
- ${{ if eq(parameters.runNodeTests, true) }}:
Expand Down
565 changes: 394 additions & 171 deletions package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
module.exports = {
displayName: "Native Auth Sample App",
displayName: "Native Auth Sample App E2E tests",
globals: {
__PORT__: 30670,
__STARTCMD__: "npm start -- --port 30670",
},
testMatch: ["<rootDir>/test/**/*.spec.ts"],
preset: "../../../../e2eTestUtils/jest-puppeteer-utils/jest-preset.js",
transform: {
"^.+\\.ts?$": "ts-jest",
},
preset: "../../e2eTestUtils/jest-puppeteer-utils/jest-preset.js",
};
6 changes: 6 additions & 0 deletions samples/msal-browser-samples/NativeAuthSample/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@
"@azure/msal-browser": "^4.0.0",
"@types/express": "^4.17.3",
"@types/jest": "^29.5.0",
"e2e-test-utils": "file:../../e2eTestUtils",
"jest": "^29.5.0",
"jest-junit": "^16.0.0",
"jose": "^2.0.7",
"ts-jest": "^29.1.0",
"typescript": "^4.9.5"
},
"jest-junit": {
"suiteNameTemplate": "Native Auth Sample Tests",
"outputDirectory": ".",
"outputName": "test-results.xml"
}
}
175 changes: 175 additions & 0 deletions samples/msal-browser-samples/NativeAuthSample/test/configUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/**
* Test configuration for Native Auth Sample E2E tests
* Contains tenant information, proxy settings, timeouts, and test user data
*/

import * as fs from 'fs';
import * as path from 'path';

/**
* Default test configuration
* Update these values based on your test environment
*/
export const testConfig = {
tenant: {
name: "MSIDLABCIAM6",
id: "fe362aec-5d43-45d1-b730-9755e60dc3b9",
labKeyVaultName: "MSIDLABCIAM6"
},

proxy: {
port: 30001,
enabled: true
},

timeouts: {
standard: 45000, // 45 seconds
auth: 60000, // 60 seconds
test: 120000 // 120 seconds
},

screenshots: {
enabled: true,
baseFolderName: "./screenshots"
}
};


/**
* Utility functions
*/
export const getTenantInfo = () => ({
name: testConfig.tenant.name,
id: testConfig.tenant.id
});

export const getProxyPort = () => testConfig.proxy.port;

export const getLabKeyVaultName = () => testConfig.tenant.labKeyVaultName;

/**
* Constants for nativeAuthConfig.json keys
* These represent the existing keys in the configuration file
*/
export const NATIVE_AUTH_CONFIG_KEYS = {
// Root level
NATIVE_AUTH: 'native_auth',

// Native auth configuration keys
EMAIL_PASSWORD_CLIENT_ID: 'native_auth.email_password_client_id',
EMAIL_CODE_CLIENT_ID: 'native_auth.email_code_client_id',
EMAIL_PASSWORD_ATTRIBUTES_CLIENT_ID: 'native_auth.email_password_attributes_client_id',
EMAIL_CODE_ATTRIBUTES_CLIENT_ID: 'native_auth.email_code_attributes_client_id',
TENANT_SUBDOMAIN: 'native_auth.tenant_subdomain',
TENANT_ID: 'native_auth.tenant_id',
SIGN_IN_EMAIL_PASSWORD_USERNAME: 'native_auth.sign_in_email_password_username',
SIGN_IN_EMAIL_CODE_USERNAME: 'native_auth.sign_in_email_code_username',
RESET_PASSWORD_USERNAME: 'native_auth.reset_password_username',
PASSWORD_SIGN_IN_EMAIL_CODE: 'native_auth.password_sign_in_email_code',
PASSWORD_PROVIDER: 'native_auth.password_provider',
KEYVAULT_URL: 'native_auth.keyvault_url'
} as const;

/**
* Utility function to parse nativeAuthConfig.json and read values based on keys
*/
export class NativeAuthConfigParser {
private static configCache: any = null;
private static readonly CONFIG_PATH = path.join(__dirname, '..', 'nativeAuthConfig.json');

/**
* Load and parse the nativeAuthConfig.json file
* @returns Parsed configuration object
*/
private static loadConfig(): any {
if (!this.configCache) {
try {
const configData = fs.readFileSync(this.CONFIG_PATH, 'utf8');
this.configCache = JSON.parse(configData);
} catch (error) {
throw new Error(`Failed to load native auth config from ${this.CONFIG_PATH}: ${error}`);
}
}
return this.configCache;
}

/**
* Get a value from the native auth configuration using dot notation
* @param key - The key to retrieve (supports dot notation like 'native_auth.email_password_client_id')
* @returns The value associated with the key
*/
static getValue(key: string): any {
const config = this.loadConfig();
const keys = key.split('.');
let value: any = config;

for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
throw new Error(`Key '${key}' not found in native auth configuration`);
}
}

return value;
}

}

/**
* Convenience function to get a value from native auth config
* @param key - The key to retrieve (supports dot notation)
* @returns The value associated with the key
*/
export const getNativeAuthConfigValue = (key: string): any => {
return NativeAuthConfigParser.getValue(key);
};

/**
* Parsed native auth configuration values
* These are the actual values from nativeAuthConfig.json
*/
export const nativeAuthConfig = {
emailPasswordClientId: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.EMAIL_PASSWORD_CLIENT_ID),
emailCodeClientId: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.EMAIL_CODE_CLIENT_ID),
emailPasswordAttributesClientId: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.EMAIL_PASSWORD_ATTRIBUTES_CLIENT_ID),
emailCodeAttributesClientId: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.EMAIL_CODE_ATTRIBUTES_CLIENT_ID),
tenantSubdomain: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.TENANT_SUBDOMAIN),
tenantId: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.TENANT_ID),
signInEmailPasswordUsername: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.SIGN_IN_EMAIL_PASSWORD_USERNAME),
signInEmailCodeUsername: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.SIGN_IN_EMAIL_CODE_USERNAME),
resetPasswordUsername: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.RESET_PASSWORD_USERNAME),
passwordSignInEmailCode: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.PASSWORD_SIGN_IN_EMAIL_CODE),
passwordProvider: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.PASSWORD_PROVIDER),
keyvaultUrl: getNativeAuthConfigValue(NATIVE_AUTH_CONFIG_KEYS.KEYVAULT_URL)
};

/**
* Test data for negative test cases and other test-specific scenarios
* These should not be replaced with real configuration values
*/
export const testData = {
// Negative test case emails
invalidUserEmail: "test123@test",
nonRegisteredEmail: "[email protected]",
incorrectPassword: "incorrect-password",
invalidPassword: "invalid-password!",
invalidOtpCode: "12345678"
};


/**
* Get test users object with real account information
* @returns Object containing test user accounts
*/
export const getTestUsers = () => ({
signInEmailPassword: nativeAuthConfig.signInEmailPasswordUsername,
signInEmailCode: nativeAuthConfig.signInEmailCodeUsername,
resetPassword: nativeAuthConfig.resetPasswordUsername,
});

/**
* Get test data for negative test cases
* @returns Object containing test data for negative scenarios
*/
export const getTestData = () => testData;
Loading