You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -69,6 +69,21 @@ In this example,
69
69
70
70
The characters `"@"` and `"#"` identify the origin and the code, respectively. (We can always introduce additional prefix characters in the future if it turns out we need to include additional information in these messages.)
71
71
72
+
Some sites use third-party `iframe`s for authentication. In such cases, the third-party `iframe`'s origin can be specified using a `"%"` field after the code.
73
+
74
+
```text
75
+
747723 is your ExampleCo authentication code.
76
+
77
+
@example.com #747723 %ecommerce.example
78
+
```
79
+
80
+
In this example,
81
+
82
+
*`"https://example.com"` is the origin the code is associated with,
83
+
*`"747723"` is the code,
84
+
*`"https://ecommerce.example"` is the origin of the third-party `iframe`, and
85
+
*`"747723 is your ExampleCo authentication code.\n\n"` is human-readable explanatory text.
86
+
72
87
## Benefits
73
88
74
89
Adoption of this format would improve the reliability of systems which today heuristically extract one-time codes from SMS, with clear end-user benefit. It improves reliability of both extracting the code and also associating that code with an origin.
Copy file name to clipboardExpand all lines: index.bs
+70-29Lines changed: 70 additions & 29 deletions
Original file line number
Diff line number
Diff line change
@@ -11,12 +11,12 @@ Editor: Sam Goto, Google https://google.com, goto@google.com
11
11
Abstract: This specification defines a way to format SMS messages for use with browser autofill features such as HTML's autocomplete=one-time-code.
12
12
Markup Shorthands: markdown yes, css no
13
13
Complain About: accidental-2119 true
14
+
Remove Multiple Links: yes
14
15
</pre>
15
16
16
17
<pre class="link-defaults">
17
18
spec:infra; type:dfn; text:size; for:list
18
19
spec:infra; type:dfn; text:string
19
-
spec:url; type:dfn; text:origin
20
20
spec:url; type:dfn; text:scheme
21
21
</pre>
22
22
@@ -30,7 +30,7 @@ Many websites deliver one-time codes over SMS. [[GSM-SMS]]
30
30
31
31
Without a standard format for such messages, programmatic extraction of codes from them has to rely on heuristics, which are often unreliable and error-prone. Additionally, without a mechanism for associating such codes with specific websites, users might be tricked into providing the code to malicious sites.
32
32
33
-
This specification defines a format for the delivery of one-time codes over SMS. This format associates the one-time code with a specific [=origin=].
33
+
This specification defines a format for the delivery of one-time codes over SMS. This format associates the one-time code with a specific website.
34
34
35
35
</div>
36
36
@@ -40,31 +40,45 @@ This specification depends on the Infra Standard. [[!INFRA]]
An <dfn export>origin-bound one-time code</dfn> is a [=tuple=] consisting of an [=origin=] and a code (a [=string=]).
43
+
An <dfn export>origin-bound one-time code</dfn> is a [=tuple=] consisting of a top-level origin (an [=/origin=]), an embedded origin (an [=/origin=] or `null`), and a code (a [=string=]).
44
44
45
45
<div class=example>
46
46
47
-
((`"https"`, `"example.com"`, `null`, `null`), `"747723"`) is an [=origin-bound one-time code=] whose origin is (`"https"`, `"example.com"`, `null`, `null`) and whose code is `"747723"`.
47
+
((`"https"`, `"example.com"`, `null`, `null`), `null`, `"747723"`) is an [=origin-bound one-time code=] whose top-level origin is (`"https"`, `"example.com"`, `null`, `null`), whose embedded origin is `null`, and whose code is `"747723"`.
48
48
49
49
</div>
50
50
51
-
<h3 id="usage">Usage</h3>
51
+
<div class=example>
52
52
53
-
Many User Agents help users fill out forms on websites. Sites can use features like <a href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-autocomplete-one-time-code">`autocomplete=one-time-code`</a> to hint to User Agents that they could assist the user with providing a one-time code to the website. [[HTML]]
53
+
((`"https"`, `"example.com"`, `null`, `null`), (`"https"`, `"ecommerce.example"`, `null`, `null`), `"747723"`) is an [=origin-bound one-timecode=] whose origin is (`"https"`, `"example.com"`, `null`, `null`), whose embedded origin is (`"https"`, `"ecommerce.example"`, `null`, `null`), and whose code is `"747723"`.
54
54
55
-
<!-- We should be able to reference autocomplete=one-time-code with Bikeshed syntax along the lines of <{html/autocomplete/one-time-code}>. See whatwg/html#5418. -->
55
+
</div>
56
56
57
-
In this section, an <dfn>active origin</dfn> is an [=origin=] of a [=top-level browsing context=]'s [=active document=].
57
+
<h3 id="usage">Usage</h3>
58
58
59
-
When a User Agent is in possession of an [=origin-bound one-time code=] and an [=active origin=] is <strong>[=same origin=]</strong> with the [=origin-bound one-timecode=]'s origin, the User Agent may assist the user with providing the [=origin-bound one-time code=]'s code to the website.
59
+
Many User Agents help users fill out forms on websites. Sites can use features like <a href="https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-autocomplete-one-time-code">`autocomplete=one-time-code`</a> to hint to User Agents that they could assist the user with providing a one-time codeto the website.[[HTML]]
60
60
61
-
When a User Agent is in possession of an [=origin-bound one-time code=] and an [=active origin=] is <strong>[=same site=] but not [=same origin=]</strong> with the [=origin-bound one-time code=]'s origin, the User Agent may assist the user with providing the [=origin-bound one-time code=]'s code to the website, and should indicate the [=origin-bound one-time code=]'s origin to the user.
61
+
Note: This specification does not impose any requirements or restrictions on the use of one-time codes which are not [=origin-bound one-time codes=].
62
62
63
-
When a User Agent is in possession of an [=origin-bound one-timecode=] and an [=active origin=] is <strong>neither [=same site=] nor [=same origin=]</strong> with the [=origin-bound one-timecode=]'s origin, the User Agent should not assist the user with providing the [=origin-bound one-time code=]'s code to the website.
63
+
<!-- We should be able to reference autocomplete=one-time-code with Bikeshed syntax along the lines of <{html/autocomplete/one-time-code}>. See whatwg/html#5418. -->
64
64
65
-
Note: because the [=scheme=] of an [=origin-bound one-time code=]'s origin is always `"https"`, assisting the user with providing [=origin-bound one-time codes=]is only available in [=secure contexts=].
65
+
User Agents determine whether or not to assist the user to provide an origin-bound one-time code to a website with [=origin-bound one-time code=]|otc| and {{Document}} |doc| by running these steps:
66
66
67
-
This specification does not impose any requirements or restrictions on the use of one-time codes which are not [=origin-bound one-time codes=].
67
+
1. If |doc| is not the [=active document=] of a [=/browsing context=], return failure.
68
+
1. Let |context| be |doc|'s [=Document/browsing context=].
69
+
1. If |context| is a [=top-level browsing context=]. run these steps:
70
+
1. If |otc|'s embedded origin is not `null`, return failure.
71
+
1. If |otc|'s top-level origin is [=same site=] with |doc|'s [=Document/origin=], return success. Otherwise, return failure.
72
+
1. If |otc|'s embedded origin is `null`, return failure.
73
+
1. If |otc|'s embedded origin is not [=same site=] with |doc|'s [=Document/origin=], return failure.
74
+
1. Set |context| to its [=parent browsing context=].
75
+
1. While |context| is not a [=top-level browsing context=], run these steps:
76
+
1. If |context|'s [=active document=]'s [=Document/origin=] is neither [=same site=] with |otc|'s embedded origin nor |otc|'s top-level origin, return failure.
77
+
1. Set |context| to its [=parent browsing context=].
78
+
1. If |context| is not a [=top-level browsing context=], return failure.
79
+
1. If |context|'s [=active document=]'s [=Document/origin=] is [=same site=] with |otc|'s top-level origin, return success. Otherwise, return failure.
80
+
81
+
Note: because the [=schemes=] of an [=origin-bound one-time code=]'s top-level and embedded origins are always `"https"`, assisting the user with providing [=origin-bound one-time codes=] is only available in [=secure contexts=].
68
82
69
83
<h2 id="format">Message format</h2>
70
84
@@ -77,11 +91,11 @@ An <dfn export>origin-bound one-time code message</dfn> is a [=string=] for whic
77
91
78
92
<em>This section is non-normative. [[#parsing]] is the normative text.</em>
79
93
80
-
[=Origin-bound one-time code messages=] can optionally begin with human-readable <dfn for="origin-bound one-time code message">explanatory text</dfn>. This consists of all but the last line of the message. The last line of the message contains both a <dfn for="origin-bound one-time code message">host</dfn> and a <dfn for="origin-bound one-time code message">code</dfn>, each prefixed with a sigil: U+0040 (@) before the <a for="origin-bound one-time code message">host</a>, and U+0023 (#) before the [=code=].
94
+
[=Origin-bound one-time code messages=] can optionally begin with human-readable <dfn for="origin-bound one-time code message">explanatory text</dfn>. This consists of all but the last line of the message. The last line of the message contains both a <dfn for="origin-bound one-time code message">top-level host</dfn> and a <dfn for="origin-bound one-time code message">code</dfn>, each prefixed with a sigil: U+0040 (@) before the [=origin-bound one-time code message/top-level host=], and U+0023 (#) before the [=code=]. Following the [=code=], an <dfn for="origin-bound one-time code message">embedded host</dfn> can be specified. It is preceeded with a U+0025 (%) sigil.
81
95
82
96
<div class="example">
83
97
84
-
In the following [=origin-bound one-time code message=], the <a for="origin-bound one-time code message">host</a>is `"example.com"`, the [=code=] is `"747723"`, and the [=explanatory text=] is `"747723 is your ExampleCo authentication code.\n\n"`.
98
+
In the following [=origin-bound one-time code message=], the [=origin-bound one-time code message/top-level host=]is `"example.com"`, the [=code=] is `"747723"`, no [=origin-bound one-time code message/embedded host=] is specified, and the [=explanatory text=] is `"747723 is your ExampleCo authentication code.\n\n"`.
85
99
86
100
```
87
101
"747723 is your ExampleCo authentication code.
@@ -91,21 +105,33 @@ In the following [=origin-bound one-time code message=], the <a for="origin-boun
91
105
92
106
</div>
93
107
94
-
The last line has to begin with U+0040 (@). (Which is to say, the <a for="origin-bound one-time code message">host</a> always comes before the [=code=] in the message.)
108
+
<div class="example">
109
+
110
+
In the following [=origin-bound one-time code message=], the [=origin-bound one-time code message/top-level host=] is `"example.com"`, the [=code=] is `"747723"`, the [=origin-bound one-time code message/embedded host=] is `"ecommerce.example"`, and the [=explanatory text=] is `"747723 is your ExampleCo authentication code.\n\n"`.
111
+
112
+
```
113
+
"747723 is your ExampleCo authentication code.
114
+
115
+
@example.com #747723 %ecommerce.example"
116
+
```
117
+
118
+
</div>
119
+
120
+
The order of fields in the last line is always [=origin-bound one-time code message/top-level host=], [=code=], and [=origin-bound one-time code message/embedded host=] (if present). Nothing can come before the [=origin-bound one-time code message/top-level host=] in the last line.
95
121
96
122
<div class="example">
97
123
98
-
The message `"something @example.com #747723"` is not an [=origin-bound one-time code message=], because its last line does not begin with U+0040 (@).
124
+
The message `"something @example.com #747723"` is not an [=origin-bound one-time code message=], because it doesn't start with the [=origin-bound one-time code message/top-level host=].
99
125
100
126
</div>
101
127
102
128
<div class="example">
103
129
104
-
The message `"#747723 @example.com"` is not an [=origin-bound one-time code message=], because its last line does not begin with U+0040 (@).
130
+
The message `"#747723 %ecommerce.example @example.com"` is not an [=origin-bound one-time code message=], because the fields are in the wrong order.
105
131
106
132
</div>
107
133
108
-
Exactly one U+0020 (SPACE) separates the two values in the last line of the message.
134
+
Exactly one U+0020 (SPACE) separates the values in the last line of the message.
109
135
110
136
<div class="example">
111
137
@@ -117,7 +143,7 @@ Trailing text in the last line is ignored. This is because we might identify add
117
143
118
144
<div class="example">
119
145
120
-
In the [=origin-bound one-time code message=] `"@example.com #747723 %future"`, the <a for="origin-bound one-time code message">host</a>is `"example.com"`, the [=code=] is `"747723"`, and the [=explanatory text=] is `""`. The trailing text `" %future"` is ignored.
146
+
In the [=origin-bound one-time code message=] `"@example.com #747723 %ecommerce.example $future"`, the [=origin-bound one-time code message/top-level host=]is `"example.com"`, the [=code=] is `"747723"`, the [=origin-bound one-time code message/embedded host=] is `"ecommerce.example"`, and the [=explanatory text=] is `""`. The trailing text `" $future"` is ignored.
121
147
122
148
</div>
123
149
@@ -128,17 +154,32 @@ In the [=origin-bound one-time code message=] `"@example.com #747723 %future"`,
128
154
To <dfn export type="abstract-op">parse an origin-bound one-time code message</dfn> from |message|, run these steps:
129
155
130
156
1. Let |line| be the [=last line=] of |message|, and |position| be 0.
131
-
1. If the code point at |position| within |line| is not U+0040 (@), return failure.
132
-
1. Advance |position| by 1.
133
-
1. Let |host| be the result of [=collecting a sequence of code points=] which are not [=ASCII whitespace=] from |line| with |position|.
134
-
1. If |host| is the empty string, return failure.
135
-
1. If the code point at |position| within |line| is not U+0020 (SPACE), return failure.
157
+
1. If |position| points past the end of |line|, return failure.
158
+
1. Let |top-level host| be the result of [=extract a marked token|extracting a marked token=] from |line| at |position| with marker U+0040 (@).
159
+
1. If |top-level host| is failure, return failure.
160
+
1. Let |top-level origin| be the [=/origin=] (`"https"`, |top-level host|, `null`, `null`).
161
+
1. If |position| points past the end of |line|, return failure.
162
+
1. If the [=code point=] at |position| within |line| is not U+0020 (SPACE), return failure.
136
163
1. Advance |position| by 1.
137
-
1. If the code point at |position| within |line| is not U+0023 (#), return failure.
164
+
1. If |position| points past the end of |line|, return failure.
165
+
1. Let |code| be the result of [=extract a marked token|extracting a marked token=] from |line| at |position| with marker U+0023 (#).
166
+
1. If |code| is failure, return failure.
167
+
1. Let |embedded origin| be null.
168
+
1. If |position| does not point past the end of |line|, and if the [=code point=] at |position| within |line| is U+0020 (SPACE), run the following steps:
169
+
1. Advance |position| by 1.
170
+
1. Let |embedded host| be the result of [=extract a marked token|extracting a marked token=] from |line| at |position| with marker U+0025 (%).
171
+
1. If |embedded host| is failure, set |embedded origin| to null. Otherwise, set |embedded origin| to the [=/origin=] (`"https"`, |embedded host|, `null`, `null`).
0 commit comments