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

[pull] master from okta:master #68

Merged
merged 1 commit into from
Nov 18, 2021
Merged
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
3 changes: 3 additions & 0 deletions packages/@okta/i18n/src/properties/login.properties
Original file line number Diff line number Diff line change
Expand Up @@ -915,6 +915,9 @@ oie.phone.invalid = Invalid Phone Number.
oie.email.label = Email
oie.email.authenticator.description = Verify with a link or code sent to your email
oie.email.mfa.title = Verify with your email
oie.email.verify.primaryButton = Send me an email
# {0} is a user's email address
oie.email.verify.subtitle = Verify with an email link or enter a code sent to <$1>{0}</$1>
# {0} is a user's email address
oie.email.verify.alternate.magicLinkToEmailAddress = An email magic link was sent to <$1>{0}</$1>.
oie.email.verify.alternate.magicLinkToYourEmail = An email magic link was sent to <$1>your email</$1>.
Expand Down
2 changes: 2 additions & 0 deletions packages/@okta/i18n/src/properties/login_ok_PL.properties
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,8 @@ oie.phone.invalid = 》Îñṽåļîð Þĥöñé Ñûɱƀéŕ· Ӝฐโ⾼ئ
oie.email.label = 》Éɱåîļ 홝한Ӝฐโ《
oie.email.authenticator.description = 》Ṽéŕîƒý ŵîţĥ å ļîñķ öŕ çöðé šéñţ ţö ýöûŕ éɱåîļ 䀕ヸ€홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
oie.email.mfa.title = 》Ṽéŕîƒý ŵîţĥ ýöûŕ éɱåîļ Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
oie.email.verify.primaryButton = 》Šéñð ɱé åñ éɱåîļ Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
oie.email.verify.subtitle = 》Ṽéŕîƒý ŵîţĥ åñ éɱåîļ ļîñķ öŕ éñţéŕ å çöðé šéñţ ţö ≤€①≥ €홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ{0}≤⁄€①≥ ฐโ《
oie.email.verify.alternate.magicLinkToEmailAddress = 》Åñ éɱåîļ ɱåĝîç ļîñķ ŵåš šéñţ ţö ≤€①≥ 한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ{0}≤⁄€①≥· ฐโ 《
oie.email.verify.alternate.magicLinkToYourEmail = 》Åñ éɱåîļ ɱåĝîç ļîñķ ŵåš šéñţ ţö ≤€①≥ýöûŕ éɱåîļ≤⁄€①≥· €홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ 《
oie.email.verify.alternate.instructions = 》Çļîçķ ţĥé ļîñķ îñ ţĥé éɱåîļ öŕ éñţéŕ ţĥé çöðé ƀéļöŵ ţö çöñţîñûé· ئ䀕ヸ€홝한Ӝฐโ⾼ئ䀕ヸ€홝한Ӝฐโ《
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
{
"version": "1.0.0",
"stateHandle": "02bINNCEMoUSz5zHuyfW0xElLeOHx7RprUV7rWlSJ3",
"expiresAt": "2021-11-10T00:26:42.000Z",
"intent": "LOGIN",
"remediation": {
"type": "array",
"value": [
{
"rel": [
"create-form"
],
"name": "authenticator-verification-data",
"relatesTo": [
"$.currentAuthenticatorEnrollment"
],
"href": "http://localhost:3000/idp/idx/challenge",
"method": "POST",
"produces": "application/ion+json; okta-version=1.0.0",
"value": [
{
"name": "authenticator",
"label": "Email",
"form": {
"value": [
{
"name": "id",
"required": true,
"value": "aut1v94GMPPMvkjbp0g4",
"mutable": false
},
{
"name": "methodType",
"type": "string",
"required": true,
"options": [
{
"label": "Email",
"value": "email"
}
]
}
]
}
},
{
"name": "stateHandle",
"required": true,
"value": "02bINNCEMoUSz5zHuyfW0xElLeOHx7RprUV7rWlSJ3",
"visible": false,
"mutable": false
}
],
"accepts": "application/json; okta-version=1.0.0"
},
{
"rel": [
"create-form"
],
"name": "select-authenticator-authenticate",
"href": "http://localhost:3000/idp/idx/challenge",
"method": "POST",
"produces": "application/ion+json; okta-version=1.0.0",
"value": [
{
"name": "authenticator",
"type": "object",
"options": [
{
"label": "Email",
"value": {
"form": {
"value": [
{
"name": "id",
"required": true,
"value": "aut1v94GMPPMvkjbp0g4",
"mutable": false
},
{
"name": "methodType",
"required": false,
"value": "email",
"mutable": false
}
]
}
},
"relatesTo": "$.authenticatorEnrollments.value[0]"
}
]
},
{
"name": "stateHandle",
"required": true,
"value": "02bINNCEMoUSz5zHuyfW0xElLeOHx7RprUV7rWlSJ3",
"visible": false,
"mutable": false
}
],
"accepts": "application/json; okta-version=1.0.0"
}
]
},
"currentAuthenticatorEnrollment": {
"type": "object",
"value": {
"profile": {
"email": "i***1@okta.com"
},
"resend": {
"rel": [
"create-form"
],
"name": "resend",
"href": "http://localhost:3000/idp/idx/challenge/resend",
"method": "POST",
"produces": "application/ion+json; okta-version=1.0.0",
"value": [
{
"name": "stateHandle",
"required": true,
"value": "02bINNCEMoUSz5zHuyfW0xElLeOHx7RprUV7rWlSJ3",
"visible": false,
"mutable": false
}
],
"accepts": "application/json; okta-version=1.0.0"
},
"type": "email",
"key": "okta_email",
"id": "eae2ep99TyJZdLB8R0g4",
"displayName": "Email",
"methods": [
{
"type": "email"
}
]
}
},
"authenticators": {
"type": "array",
"value": [
{
"type": "email",
"key": "okta_email",
"id": "aut1v94GMPPMvkjbp0g4",
"displayName": "Email",
"methods": [
{
"type": "email"
}
]
}
]
},
"authenticatorEnrollments": {
"type": "array",
"value": [
{
"profile": {
"email": "i***1@okta.com"
},
"type": "email",
"key": "okta_email",
"id": "eae2ep99TyJZdLB8R0g4",
"displayName": "Email",
"methods": [
{
"type": "email"
}
]
}
]
},
"user": {
"type": "object",
"value": {
"id": "00u2ep8CG3BouMb750g4",
"identifier": "testUser@okta.com",
"profile": {
"firstName": "Test",
"lastName": "user1",
"timeZone": "America/Los_Angeles",
"locale": "en_US"
}
}
},
"cancel": {
"rel": [
"create-form"
],
"name": "cancel",
"href": "http://localhost:3000/idp/idx/cancel",
"method": "POST",
"produces": "application/ion+json; okta-version=1.0.0",
"value": [
{
"name": "stateHandle",
"required": true,
"value": "02bINNCEMoUSz5zHuyfW0xElLeOHx7RprUV7rWlSJ3",
"visible": false,
"mutable": false
}
],
"accepts": "application/json; okta-version=1.0.0"
},
"app": {
"type": "object",
"value": {
"name": "okta_enduser",
"label": "Okta Dashboard",
"id": "0oazy63LqpLSP2B6r0g3"
}
}
}
4 changes: 3 additions & 1 deletion src/v2/view-builder/ViewFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import ChallengeWebauthnView from './views/webauthn/ChallengeWebauthnView';
// email
import EnrollAuthenticatorEmailView from './views/email/EnrollAuthenticatorEmailView';
import ChallengeAuthenticatorEmailView from './views/email/ChallengeAuthenticatorEmailView';
import ChallengeAuthenticatorDataEmailView from './views/email/ChallengeAuthenticatorDataEmailView';

// app (okta verify)
import EnrollPollOktaVerifyView from './views/ov/EnrollPollOktaVerifyView';
Expand Down Expand Up @@ -229,7 +230,8 @@ const VIEWS_MAPPING = {
},
[RemediationForms.AUTHENTICATOR_VERIFICATION_DATA]: {
[AUTHENTICATOR_KEY.PHONE]: ChallengeAuthenticatorDataPhoneView,
[AUTHENTICATOR_KEY.OV]: ChallengeAuthenticatorDataOktaVerifyView
[AUTHENTICATOR_KEY.OV]: ChallengeAuthenticatorDataOktaVerifyView,
[AUTHENTICATOR_KEY.EMAIL]: ChallengeAuthenticatorDataEmailView,
},
[RemediationForms.FAILURE_REDIRECT]: {
[DEFAULT]: AutoRedirectView,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { loc, View } from 'okta';
import hbs from 'handlebars-inline-precompile';
import BaseAuthenticatorEmailView from './BaseAuthenticatorEmailView';

const BaseAuthenticatorEmailForm = BaseAuthenticatorEmailView.prototype.Body;

const SubtitleView = View.extend({
template: hbs`
<div class="okta-form-subtitle" data-se="o-form-explain">
{{i18n
code="oie.email.verify.subtitle"
bundle="login"
arguments="email"
$1="<span class='strong no-translate'>$1</span>"
}}
</div>
`,

getTemplateData() {
const email = this.options.appState.get('currentAuthenticatorEnrollment')?.profile?.email;
return {
email,
};
},
});

const Body = BaseAuthenticatorEmailForm.extend(
{
title() {
return loc('oie.email.mfa.title', 'login');
},

save() {
return loc('oie.email.verify.primaryButton', 'login');
},

postRender() {
BaseAuthenticatorEmailForm.prototype.postRender.apply(this, arguments);
this.add(SubtitleView, {
prepend: true,
selector: '.o-form-info-container',
});
},

getUISchema() {
// Prevent from displaying radio buttons on the UI
const uiSchemas = BaseAuthenticatorEmailForm.prototype.getUISchema.apply(this, arguments);
return uiSchemas.filter(schema => schema.name !== 'authenticator.methodType');
},
},
);

export default BaseAuthenticatorEmailView.extend({
Body,
});
57 changes: 53 additions & 4 deletions test/testcafe/spec/ChallengeAuthenticatorEmail_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import terminalTransferedEmail from '../../../playground/mocks/data/idp/idx/term
import sessionExpired from '../../../playground/mocks/data/idp/idx/error-session-expired';
import tooManyRequest from '../../../playground/mocks/data/idp/idx/error-429-too-many-request';
import apiLimitExeeeded from '../../../playground/mocks/data/idp/idx/error-429-api-limit-exceeded';
import emailVerificationSendEmailData from '../../../playground/mocks/data/idp/idx/authenticator-verification-data-email';

const emailVerificationEmptyProfile = JSON.parse(JSON.stringify(emailVerificationNoProfile));
// add empty profile to test
Expand All @@ -33,6 +34,12 @@ const logger = RequestLogger(/challenge|challenge\/poll|challenge\/answer/,
}
);

const sendEmailMock = RequestMock()
.onRequestTo('http://localhost:3000/idp/idx/introspect')
.respond(emailVerificationSendEmailData)
.onRequestTo('http://localhost:3000/idp/idx/challenge')
.respond(emailVerification);

const validOTPmock = RequestMock()
.onRequestTo('http://localhost:3000/idp/idx/introspect')
.respond(emailVerification)
Expand Down Expand Up @@ -157,6 +164,48 @@ async function setup(t) {
return challengeEmailPageObject;
}

test
.requestHooks(sendEmailMock)('send email screen should have right labels', async t => {
const challengeEmailPageObject = await setup(t);
await checkConsoleMessages({
controller: null,
formName: 'authenticator-verification-data',
authenticatorKey: 'okta_email',
methodType: 'email',
});

const pageTitle = challengeEmailPageObject.getFormTitle();
const saveBtnText = challengeEmailPageObject.getSaveButtonLabel();
await t.expect(pageTitle).eql('Verify with your email');
await t.expect(saveBtnText).eql('Send me an email');

const emailAddress = emailVerificationSendEmailData.currentAuthenticatorEnrollment.value.profile.email;
await t.expect(challengeEmailPageObject.getFormSubtitle())
.eql(`Verify with an email link or enter a code sent to ${emailAddress}`);

// Verify links (switch authenticator link not present since there are no other authenticators available)
await t.expect(await challengeEmailPageObject.switchAuthenticatorLinkExists()).notOk();
await t.expect(await challengeEmailPageObject.signoutLinkExists()).ok();
await t.expect(challengeEmailPageObject.getSignoutLinkText()).eql('Back to sign in');
});

test
.requestHooks(sendEmailMock)('send me an email button should take to challenge email authenticator screen', async t => {
const challengeEmailPageObject = await setup(t);
await challengeEmailPageObject.clickNextButton();
const pageTitle = challengeEmailPageObject.getFormTitle();
await t.expect(pageTitle).eql('Verify with your email');

const emailAddress = emailVerification.currentAuthenticatorEnrollment.value.profile.email;
await t.expect(challengeEmailPageObject.getFormSubtitle())
.eql(`An email magic link was sent to ${emailAddress}. Click the link in the email or enter the code below to continue.`);

// Verify links (switch authenticator link not present since there are no other authenticators available)
await t.expect(await challengeEmailPageObject.switchAuthenticatorLinkExists()).notOk();
await t.expect(await challengeEmailPageObject.signoutLinkExists()).ok();
await t.expect(challengeEmailPageObject.getSignoutLinkText()).eql('Back to sign in');
});

test
.requestHooks(validOTPmock)('challenge email authenticator screen has right labels', async t => {
const challengeEmailPageObject = await setup(t);
Expand All @@ -168,14 +217,14 @@ test
});
await challengeEmailPageObject.clickEnterCodeLink();

const pageTitle = challengeEmailPageObject.getPageTitle();
const pageTitle = challengeEmailPageObject.getFormTitle();
const saveBtnText = challengeEmailPageObject.getSaveButtonLabel();
await t.expect(saveBtnText).contains('Verify');
await t.expect(pageTitle).contains('Verify with your email');
await t.expect(pageTitle).eql('Verify with your email');
await t.expect(saveBtnText).eql('Verify');

const emailAddress = emailVerification.currentAuthenticatorEnrollment.value.profile.email;
await t.expect(challengeEmailPageObject.getFormSubtitle())
.contains(`An email magic link was sent to ${emailAddress}. Click the link in the email or enter the code below to continue.`);
.eql(`An email magic link was sent to ${emailAddress}. Click the link in the email or enter the code below to continue.`);

// Verify links (switch authenticator link not present since there are no other authenticators available)
await t.expect(await challengeEmailPageObject.switchAuthenticatorLinkExists()).notOk();
Expand Down