-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathdraft-ietf-oauth-security-topics.xml
1671 lines (1562 loc) · 90.1 KB
/
draft-ietf-oauth-security-topics.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<!--
This template is for creating an Internet Draft using xml2rfc, which
is available here: http://xml.resource.org.
-->
<!DOCTYPE rfc SYSTEM "rfc2629.dtd" [
<!-- One method to get references from the online citation libraries.
There has to be one entity for each item to be referenced.
An alternate method (rfc include) is described in the references. -->
<!ENTITY RFC2119 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2119.xml">
<!ENTITY RFC2629 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.2629.xml">
<!ENTITY RFC3552 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.3552.xml">
<!ENTITY I-D.narten-iana-considerations-rfc2434bis SYSTEM "http://xml.resource.org/public/rfc/bibxml3/reference.I-D.narten-iana-considerations-rfc2434bis.xml">
]>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?xml-stylesheet type='text/xsl' href='rfc2629.xslt' ?>
<?rfc strict="yes" ?>
<!-- give errors regarding ID-nits and DTD validation -->
<!-- control the table of contents (ToC) -->
<?rfc toc="yes"?>
<!-- generate a ToC -->
<?rfc tocdepth="4"?>
<!-- the number of levels of subsections in ToC. default: 3 -->
<!-- control references -->
<?rfc symrefs="yes"?>
<!-- use symbolic references tags, i.e, [RFC2119] instead of [1] -->
<?rfc sortrefs="yes" ?>
<!-- sort the reference entries alphabetically -->
<!--
control vertical white space (using these PIs as follows is
recommended by the RFC Editor)
-->
<?rfc compact="yes" ?>
<!-- do not start each main section on a new page -->
<?rfc subcompact="no" ?>
<!-- keep one blank line between list items -->
<!-- end of list of popular I-D processing instructions -->
<rfc category="bcp"
docName="draft-ietf-oauth-security-topics-11"
ipr="trust200902">
<!--
category values: std, bcp, info, exp, and historic ipr values:
full3667, noModification3667, noDerivatives3667 you can add the
attributes updates="NNNN" and obsoletes="NNNN" they will automatically
be output with "(if approved)"
-->
<!-- ***** FRONT MATTER ***** -->
<front>
<!--
The abbreviated title is used in the page header - it is only
necessary if the full title is longer than 39 characters
-->
<title abbrev="Security Topics">OAuth 2.0 Security Best Current Practice</title>
<author fullname="Torsten Lodderstedt" initials="T." role="editor"
surname="Lodderstedt">
<organization>yes.com</organization>
<address>
<email>torsten@lodderstedt.net</email>
<!-- uri and facsimile elements may also be added -->
</address>
</author>
<author fullname="John Bradley" initials="J." surname="Bradley">
<organization>Yubico</organization>
<address>
<email>ve7jtb@ve7jtb.com</email>
</address>
</author>
<author fullname="Andrey Labunets" initials="A." surname="Labunets">
<organization>Facebook</organization>
<address>
<email>isciurus@fb.com</email>
</address>
</author>
<author fullname="Daniel Fett" initials="D." surname="Fett">
<organization>yes.com</organization>
<address>
<email>mail@danielfett.de</email>
</address>
</author>
<date day="19" month="November" year="2018" />
<!-- Meta-data Declarations -->
<area>Security Area</area>
<workgroup>Open Authentication Protocol</workgroup>
<!--
WG name at the upperleft corner of the doc, IETF is fine for
individual submissions. If this element is not present, the default
is "Network Working Group", which is used by the RFC Editor as a nod
to the history of the IETF.
-->
<keyword>security</keyword>
<keyword>oauth2</keyword>
<keyword>best current practice</keyword>
<!--
Keywords will be incorporated into HTML output files in a meta tag
but they have no effect on text or nroff output. If you submit your
draft to the RFC Editor, the keywords will be used for the search
engine.
-->
<abstract>
<t>This document describes best current security practice for OAuth 2.0.
It updates and extends the OAuth 2.0 Security Threat Model to incorporate
practical experiences gathered since OAuth 2.0 was published and covers
new threats relevant due to the broader application of OAuth 2.0.</t>
</abstract>
</front>
<middle>
<section anchor="Introduction" title="Introduction">
<t>It's been a while since OAuth has been published in
<xref target="RFC6749">RFC 6749</xref> and <xref target="RFC6750">RFC 6750</xref>.
Since publication, OAuth 2.0 has gotten massive traction in the market and became the
standard for API protection and, as foundation of
<xref target="OpenID">OpenID Connect</xref>, identity
providing. While OAuth was used in a variety of scenarios and different kinds of
deployments, the following challenges could be observed:
<list style="symbols">
<t>OAuth implementations are being attacked through known implementation
weaknesses and anti-patterns (CSRF, referrer header). Although most of these
threats are discussed in the
<xref target="RFC6819">OAuth 2.0 Threat Model and Security Considerations</xref>,
continued exploitation
demonstrates there may be a need for more specific recommendations or that the existing
mitigations are too difficult to deploy.</t>
<t>Technology has changed, e.g., the way browsers treat fragments in some situations,
which may change the implicit grant's underlying security model.</t>
<t>OAuth is used in much more dynamic setups than originally anticipated, creating new
challenges with respect to security. Those challenges go beyond the original
scope of <xref target="RFC6749">RFC 6749</xref>,
<xref target="RFC6749">RFC 6750</xref>, and
<xref target="RFC6819">RFC 6819</xref>.</t>
</list>
</t>
<t>OAuth initially assumed a static relationship between client, authorization
server and resource servers. The URLs of AS and RS were known to the client
at deployment time and built an anchor for the trust relationship among those
parties. The validation whether the client talks to a legitimate server was based on
TLS server authentication (see <xref target="RFC6819"/>, Section 4.5.4).
With the increasing adoption of OAuth, this simple model dissolved and, in
several scenarios, was replaced by a dynamic establishment of the relationship
between clients on one side and the authorization and resource servers of a
particular deployment on the other side. This way the same client could be
used to access services of different providers (in case of standard APIs, such
as e-Mail or OpenID Connect) or serves as a frontend to a particular tenant in a
multi-tenancy.
Extensions of OAuth, such as <xref target="RFC7591"/> and
<xref target="RFC8414"/> were developed in order to support
the usage of OAuth in dynamic scenarios.
As a challenge to the community, such usage scenarios open up new attack angles,
which are discussed in this document.</t>
<t>The remainder of the document is organized as follows: The next section
summarizes the most important recommendations of the OAuth working group
for every OAuth implementor. Afterwards, a detailed analysis of the threats and
implementation issues which can be found in the wild today is given
along with a discussion of potential countermeasures.</t>
</section>
<section anchor="recommendations" title="Recommendations">
<t>This section describes the set of security mechanisms the OAuth working group
recommendeds to OAuth implementers.</t>
<section anchor="rec_redirect" title="Protecting Redirect-Based Flows">
<t>Authorization servers MUST utilize exact matching of client redirect URIs against
pre-registered URIs. This measure contributes to the prevention of leakage of
authorization codes and access tokens (depending on the grant type). It also helps
to detect mix-up attacks.</t>
<t>Clients SHOULD avoid forwarding the user’s browser to a URI obtained from a
query parameter since such a function could be utilized to exfiltrate authorization
codes and access tokens. If there is a strong need for this kind of redirects, clients
are advised to implement appropriate countermeasures against open redirection,
e.g., as described by the <xref target="owasp">OWASP</xref>.</t>
<t>Clients MUST prevent CSRF and ensure that each authorization response is only
accepted once. One-time use CSRF tokens carried in the
<spanx style="verb">state</spanx> parameter, which are securely bound to the
user agent, SHOULD be used for that purpose.</t>
<t>In order to prevent mix-up attacks, clients MUST only process redirect responses
of the OAuth authorization server they send the respective request to and from the
same user agent this authorization request was initiated with. Clients MUST memorize
which authorization server they sent an authorization request to and bind this
information to the user agent and ensure any sub-sequent messages are sent to the
same authorization server. Clients SHOULD use AS-specific redirect URIs as a means
to identify the AS a particular response came from.</t>
<t>Note: <xref target="I-D.bradley-oauth-jwt-encoded-state"></xref> gives advice
on how to implement CSRF prevention and AS matching using signed JWTs in the
<spanx style="verb">state</spanx> parameter.</t>
<section anchor="ac" title="Authorization Code Grant">
<t>Clients utilizing the authorization grant type MUST use
<xref target="RFC7636">PKCE</xref> in order to (with the help
of the authorization server) detect and prevent attempts to inject (replay)
authorization codes
into the authorization response. The PKCE challenges must be transaction-specific and
securely bound to the user agent in which the transaction was started. OpenID
Connect clients MAY use the <spanx style="verb">nonce</spanx> parameter of the
OpenID Connect authentication request as specified in <xref target="OpenID"/>
in conjunction with the corresponding ID Token
claim for the same purpose.</t>
<t>Note: although PKCE so far was recommended as
a mechanism to protect native apps, this advice applies to all kinds of OAuth clients,
including web applications.</t>
<t>Authorization servers MUST bind authorization codes to a certain client and
authenticate it using an appropriate mechanism (e.g. client credentials or PKCE).</t>
<t>Authorization servers SHOULD furthermore consider the recommendations given in
<xref target="RFC6819"/>, Section 4.4.1.1, on authorization code replay
prevention.</t>
</section>
<section title="Implicit Grant">
<t>The implicit grant (response type "token") and other response types causing
the authorization server to issue access tokens in the authorization response
are vulnerable to access token leakage and access token replay as described in
<xref target="insufficient_uri_validation"/>,
<xref target="credential_leakage_referrer"/>,
<xref target="browser_history"/>, and <xref target="access_token_injection"/>.</t>
<t>Moreover, no viable mechanism exists to cryptographically bind access tokens issued
in the authorization response to a certain client as it is recommended
in <xref target="token_replay_prevention"/>. This makes replay detection
for such access tokens at resource servers impossible.</t>
<t>In order to avoid these issues, Clients SHOULD NOT use the implicit grant or
any other response type causing the authorization server to issue an access token in
the authorization response.</t>
<t>Clients SHOULD instead use the response type "code" (aka authorization code
grant type) as specified in <xref target="ac"/> or any other response type that
causes the authorization server to issue access tokens in the token response.
This allows the authorization server to detect replay attempts and
generally reduces the attack surface since access tokens are not exposed in URLs. It
also allows the authorization server to sender-constrain the issued tokens.</t>
</section>
</section>
<section anchor="token_replay_prevention" title="Token Replay Prevention">
<t>Authorization servers SHOULD use TLS-based methods for sender constrained access
tokens as described in <xref target="pop_tokens"/>, such as token
binding <xref target="I-D.ietf-oauth-token-binding"></xref> or Mutual TLS for
OAuth 2.0 <xref target="I-D.ietf-oauth-mtls"></xref> in order to prevent token replay.
It is also recommended to use end-to-end TLS whenever possible.</t>
</section>
<section title="Access Token Privilege Restriction">
<t>The privileges associated with an access token SHOULD be restricted to the
minimum required for the particular application or use case. This prevents
clients from exceeding the privileges authorized by the resource owner. It also
prevents users from exceeding their privileges authorized by the respective
security policy. Privilege restrictions also limit the impact of token leakage
although more effective counter-measures are described in
<xref target="token_replay_prevention"></xref>.</t>
<t>In particular, access tokens SHOULD be restricted to certain resource servers,
preferably to a single resource server. To put this into effect, the authorization server
associates the access token with certain resource servers and every resource server
is obliged to verify for every request, whether the access token sent with that request
was meant to be used for that particular resource server. If not, the resource server
MUST refuse to serve the respective request. Clients and authorization servers MAY
utilize the parameters
<spanx style="verb">scope</spanx> or <spanx style="verb">resource</spanx> as
specified in <xref target="RFC6749"/> and
<xref target="I-D.ietf-oauth-resource-indicators"/>, respectively, to determine
the resource server they want to access.</t>
<t>Additionally, access tokens SHOULD be restricted to certain resources and actions
on resource servers or resources. To put this into effect, the authorization server
associates the access token with the respective resource and actions and every resource
server is obliged to verify for every request, whether the access token sent with that
request was meant to be used for that particular action on the particular resource.
If not, the resource server must refuse to serve the respective request.
Clients and authorization servers MAY utilize the
parameter <spanx style="verb">scope</spanx> as specified in <xref target="RFC6749"/>
to determine those resources and/or actions.</t>
</section>
</section>
<section title="Attacks and Mitigations">
<t>
This section gives a detailed description of attacks on OAuth implementations,
along with potential countermeasures. This section complements and enhances the
description given in <xref target="RFC6819"/>.
</t>
<section anchor="insufficient_uri_validation" title="Insufficient Redirect URI Validation">
<t>Some authorization servers allow clients to register redirect URI
patterns instead of
complete redirect URIs. In those cases, the authorization server,
at runtime, matches the actual redirect URI parameter value at the
authorization endpoint against this pattern. This approach
allows clients to encode transaction state into additional
redirect URI parameters or to register just a single pattern for
multiple redirect URIs. As a downside, it turned out to be more
complex to implement and error prone to manage than exact
redirect URI matching. Several successful attacks have been
observed in the wild, which utilized flaws in the pattern
matching implementation or concrete configurations. Such a flaw
effectively breaks client identification or authentication
(depending on grant and client type) and allows the attacker to
obtain an authorization code or access token, either:
<list style="symbols">
<t>by directly sending the user agent to a URI under the attackers
control or</t>
<t>by exposing the OAuth credentials to an attacker by utilizing an
open redirector at the client in conjunction with the way user agents
handle URL fragments.</t>
</list>
</t>
<section title="Attacks on Authorization Code Grant" anchor="insufficient_uri_validation_acg">
<t>For a public client using the grant type code, an attack
would look as follows: </t>
<t>Let's assume the redirect URL pattern "https://*.somesite.example/*" had been registered
for the client "s6BhdRkqt3". This pattern allows redirect URIs pointing to any
host residing in the domain somesite.example. So if an attacker manages to
establish a host or subdomain in somesite.example he can impersonate the
legitimate client. Assume the attacker sets up the host
"evil.somesite.example".</t>
<t>
<list style="format (%d)" counter="my_count">
<t>The attacker needs to trick the user into opening a tampered URL
in his browser, which launches a page under the attacker's control,
say "https://www.evil.example".</t>
<t>This URL initiates an authorization request with the client id
of a legitimate client to the authorization endpoint. This is the
example authorization request (line breaks are for display purposes only):
</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[GET /authorize?response_type=code&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fevil.somesite.example%2Fcb HTTP/1.1
Host: server.somesite.example]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="my_count">
<t>The authorization server validates the redirect URI in order to identify the
client. Since the pattern allows arbitrary domains host names in
"somesite.example", the authorization request is processed under the legitimate
client's identity. This includes the way the request for user consent is
presented to the user. If auto-approval is allowed (which is not
recommended for public clients according to <xref target="RFC6749"/>), the attack can be
performed even easier.</t>
<t>If the user does not recognize the attack, the code is issued and directly
sent to the attacker's client.</t>
<t>Since the attacker impersonated a public client, it can directly exchange
the code for tokens at the respective token endpoint.</t>
</list>
</t>
<t>Note: This attack will not directly work for confidential clients, since the
code exchange requires authentication with the legitimate client's
secret. The attacker will need to impersonate or utilize the legitimate client to
redeem the code (e.g., by performing a code injection attack). This kind
of injections is covered in
Section <xref format="title" target="code_injection"/>.</t>
</section>
<section title="Attacks on Implicit Grant">
<t>The attack described above works for the implicit grant as well. If the attacker
is able to send the
authorization response to a URI under his control, he will directly get
access to the fragment carrying the access token.</t>
<t>Additionally, implicit clients can be subject to a further kind of attacks.
It utilizes the fact that user agents re-attach fragments to the destination URL
of a redirect if the location header does not contain a
fragment (see <xref target="RFC7231"/>, Section 9.5). The attack described here
combines this behavior with the client as an open redirector
in order to get access to access tokens. This allows circumvention even of
strict redirect URI patterns (but not strict URL matching!).</t>
<t>Assume the pattern for client "s6BhdRkqt3" is
"https://client.somesite.example/cb?*", i.e., any parameter is allowed for
redirects to "https://client.somesite.example/cb". Unfortunately, the client
exposes an open redirector. This endpoint supports a parameter
"redirect_to" which takes a target URL and will send the browser to
this URL using an HTTP Location header redirect 303.</t>
<t>
<list style="format (%d)" counter="my_count1">
<t>Same as above, the attacker needs to trick the user into opening a
tampered URL in his browser, which launches a page under the attacker's control,
say "https://www.evil.example".</t>
<t>The URL initiates an authorization request, which is very
similar to the attack on the code flow. As differences, it utilizes the
open redirector by encoding "redirect_to=https://client.evil.example" into
the redirect URI and it uses the response type "token" (line breaks
are for display purposes only):</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[GET /authorize?response_type=token&client_id=s6BhdRkqt3&state=xyz
&redirect_uri=https%3A%2F%2Fclient.somesite.example%2Fcb%26redirect_to
%253Dhttps%253A%252F%252Fclient.evil.example%252Fcb HTTP/1.1
Host: server.somesite.example]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="my_count1">
<t>Since the redirect URI matches the registered pattern, the authorization server
allows the request and sends the resulting access token with a 303 redirect (some
response parameters are omitted for better readability)</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[HTTP/1.1 303 See Other
Location: https://client.somesite.example/cb?
redirect_to%3Dhttps%3A%2F%2Fclient.evil.example%2Fcb
#access_token=2YotnFZFEjr1zCsicMWpAA&...]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="my_count1">
<t>At example.com, the request arrives at the open redirector. It will read the
redirect parameter and will issue an HTTP 303 Location header redirect to the URL "https://client.evil.example/cb".</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[HTTP/1.1 303 See Other
Location: https://client.evil.example/cb]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="my_count1">
<t>Since the redirector at client.somesite.example does not include a fragment in the Location header,
the user agent will re-attach the original fragment <vspace/>"#access_token=2YotnFZFEjr1zCsicMWpAA&..."
to the URL and will navigate to the following URL:</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[https://client.evil.example/cb#access_token=2YotnFZFEjr1zCsicMWpAA&...]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="my_count1">
<t>The attacker's page at client.evil.example can access the fragment and obtain the access token.</t>
</list>
</t>
</section>
<section title="Proposed Countermeasures">
<t>The complexity of implementing and managing pattern matching correctly
obviously causes security issues. This document therefore proposes to
simplify the required logic and configuration by using exact redirect URI matching only.
This means the authorization server must compare the two
URIs using simple string comparison as defined in <xref target="RFC3986"/>, Section 6.2.1..</t>
<t>Additional recommendations:
<list style="symbols">
<t>Servers on which callbacks are hosted must not expose open redirectors (see <xref target="Open.Redirection"/>).</t>
<t>Clients MAY drop fragments via intermediary URLs with "fix fragments"
(see <xref target="fb_fragments"/>) to prevent the user agent from appending any unintended fragments.</t>
<t>Clients SHOULD use the authorization code response type instead of response types causing access token issuance at the
authorization endpoint. This offers countermeasures against reuse of leaked credentials through
the exchange process with the authorization server and token replay through certificate binding
of the access tokens.</t>
</list>
</t>
<t>As an alternative to exact redirect URI matching, the AS could also authenticate clients, e.g., using
<xref target="I-D.ietf-oauth-jwsreq"/>.</t>
</section>
</section>
<section anchor="credential_leakage_referrer" title="Credential Leakage via Referrer Headers">
<t>Authorization codes or values of <spanx style="verb">state</spanx> can
unintentionally be disclosed to attackers through the referrer header, by leaking either
from a client's web site or from an AS's web site. Note: even if specified otherwise in
<xref target="RFC2616"/>, section 14.36, the same may happen to access tokens conveyed in
URI fragments due to browser implementation issues as illustrated by
<xref target="bug.chromium">Chromium Issue 168213</xref>.
</t>
<section title="Leakage from the OAuth client">
<t>
This requires that the client, as a result of a successful
authorization request, renders a page that
</t>
<t>
<list style="symbols">
<t>contains links to other pages under the attacker's control (ads, faq, ...) and a
user clicks on such a link, or</t>
<t>includes third-party content (iframes, images, etc.) for example if
the page contains user-generated content (blog).</t>
</list>
</t>
<t>
As soon as the browser navigates to the attacker's page or loads the
third-party content, the attacker receives the authorization response URL
and can extract <spanx style="verb">code</spanx>, <spanx style="verb">access token</spanx>,
or <spanx style="verb">state</spanx>.
</t>
</section>
<section title="Leakage from the Authorization Server">
<t>In a similar way, an attacker can learn <spanx
style="verb">state</spanx> if the authorization endpoint at the authorization server
contains links or third-party content as above.</t>
</section>
<section title="Consequences">
<t>An attacker that learns a valid code or access token through a
referrer header can perform the attacks as described in <xref
target="insufficient_uri_validation_acg"/>, <xref
target="code_injection"/>, and <xref
target="access_token_injection"/>. If the attacker learns <spanx
style="verb">state</spanx>, the CSRF protection achieved by using <spanx
style="verb">state</spanx> is lost, resulting in CSRF attacks as described in <xref
target="RFC6819"/>, Section 4.4.1.8..
</t>
</section>
<section title="Proposed Countermeasures">
<t>The page rendered as a result of the OAuth authorization response and the
authorization endpoint SHOULD not include third-party resources or
links to external sites.</t>
<t>The following measures further reduce the chances of a successful attack:</t>
<t>
<list style="symbols">
<t>Bind authorization code to a confidential client or PKCE challenge.
In this case, the attacker lacks the secret to request the code exchange.</t>
<t>Authorization codes SHOULD be invalidated by the AS after their first use at the
token endpoint. For example, if an AS invalidated the code after the legitimate client
redeemed it, the attacker would fail exchanging this code later. (This does not
mitigate the attack if the attacker manages to exchange the code for a token before the
legitimate client does so.)</t>
<t>The <spanx style="verb">state</spanx> value SHOULD be invalidated by the client
after its first use at the redirection endpoint. If this is implemented, and an
attacker receives a token through the referrer header from the client's web site, the
<spanx style="verb">state</spanx> was already used, invalidated by the client and
cannot be used again by the attacker. (This does not help if the <spanx
style="verb">state</spanx> leaks from the AS's web site, since then the <spanx
style="verb">state</spanx> has not been used at the redirection endpoint at the client
yet.)</t>
<t>Suppress the referrer header by adding the attribute
<spanx style="verb">rel="noreferrer"</spanx> to HTML links or by
applying an appropriate Referrer Policy <xref target="webappsec-referrer-policy"/>
to the document (either as part of the "referrer" meta attribute or by
setting a Referrer-Policy header).</t>
<t>Use authorization code instead of response types causing access token issuance
from the authorization endpoint. This provides countermeasures against
leakage on the OAuth protocol level through the code exchange process with
the authorization server.</t>
<t>Additionally, one might use the form post response mode instead of redirect
for authorization response (see <xref target="oauth-v2-form-post-response-mode"/>).</t>
</list>
</t>
</section>
</section>
<section anchor="browser_history" title="Attacks through the Browser History">
<t>
Authorization codes and access tokens can end up in the browser's history of visited URLs, enabling the attacks described in the following.
</t>
<section title="Code in Browser History">
<t>When a browser navigates to "client.example/redirection_endpoint?code=abcd" as a result
of a redirect from a provider's authorization endpoint, the URL including the
authorization code may end up in the browser's history. An attacker
with access to the device could obtain the code and try to replay it.</t>
<t>Proposed countermeasures:
<list style="symbols">
<t>Authorization code replay prevention as described in
<xref target="RFC6819"/>, Section 4.4.1.1, and <xref target="code_injection"/></t>
<t>Use form post response mode instead of redirect for authorization
response (see <xref target="oauth-v2-form-post-response-mode"/>)</t>
</list>
</t>
</section>
<section title="Access Token in Browser History">
<t>An access token may end up in the browser history if a a client or just a web
site, which already has a token, deliberately navigates to a page like
"provider.com/get_user_profile?access_token=abcdef.".
Actually <xref target="RFC6750"/> discourages this practice and asks to transfer
tokens via a header, but in practice web sites often just pass access token in
query parameters.</t>
<t>In case of implicit grant, a URL like
"client.example/redirection_endpoint#access_token=abcdef" may also end up in the browser
history as a result of a redirect from a provider's authorization endpoint.</t>
<t>Proposed countermeasures:
<list style="symbols">
<t>Replace implicit flow with postmessage communication or
the authorization code grant</t>
<t>Never pass access tokens in URL query parameters</t>
</list>
</t>
</section>
</section>
<section title="Mix-Up">
<t>Mix-up is an attack on scenarios where an OAuth client interacts with multiple
authorization servers, as is usually the case when dynamic registration is used. The goal
of the attack is to obtain an authorization code or an access token by tricking the client
into sending those credentials to the attacker instead of using them at the respective
endpoint at the authorization/resource server.</t>
<section title="Attack Description">
<t>For a detailed attack description, refer to <xref target="arXiv.1601.01229"/> and <xref
target="I-D.ietf-oauth-mix-up-mitigation"/>. The description here closely follows <xref
target="arXiv.1601.01229"/>, with variants of the attack outlined below.</t>
<t>Preconditions: For the attack to work, we assume that
<list style="format (%d)">
<t>the implicit or authorization code grant are used with
multiple AS of which one is considered "honest" (H-AS) and
one is operated by the attacker (A-AS),</t>
<t>the client stores the AS chosen by the user in a session
bound to the user's browser and uses the same redirection
endpoint URI for each AS, and</t>
<t>the attacker can manipulate the first request/response
pair from a user's browser to the client (in which the user
selects a certain AS and is then redirected by the client to
that AS).</t>
</list>
Some of the attack variants described below require different preconditions.
</t>
<t>In the following, we assume that the client is registered
with H-AS (URI: "https://honest.as.example", client id:
7ZGZldHQ) and with A-AS (URI: "https://attacker.example",
client id: 666RVZJTA).</t>
<t>Attack on the authorization code grant:
<list style="format (%d)" counter="counter_mixup_acg">
<t>The user selects to start the grant using H-AS (e.g., by clicking on a button at the
client's website).</t>
<t>The attacker intercepts this request and changes the user's selection to "A-AS".</t>
<t>The client stores in the user's session that the user
selected "A-AS" and redirects the user to A-AS's
authorization endpoint by sending the following response:
</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[HTTP/1.1 303 See Other
Location: https://attacker.example/authorize?response_type=code&client_id=666RVZJTA]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="counter_mixup_acg">
<t>Now the attacker intercepts this response and changes the
redirection such that the user is being redirected to H-AS.
The attacker also replaces the client id of the client at
A-AS with the client's id at H-AS, resulting in the following response being sent to the browser:
</t>
</list>
</t>
<t>
<figure>
<artwork><![CDATA[HTTP/1.1 303 See Other
Location: https://honest.as.example/authorize?response_type=code&client_id=7ZGZldHQ]]></artwork>
</figure>
</t>
<t>
<list style="format (%d)" counter="counter_mixup_acg">
<t anchor="list_mixup_acg_after_authep">Now, the user authorizes the client to access her
resources at H-AS. H-AS issues a code and sends it (via the browser) back to the
client.</t>
<t>Since the client still assumes that the code was issued by A-AS, it will try to redeem
the code at A-AS's token endpoint.</t>
<t>The attacker therefore obtains code and can either exchange the code for an access
token (for public clients) or perform a code injection attack as described in
<xref target="code_injection"/>.</t>
</list>
</t>
<t>Variants:
<list hangIndent="8" style="hanging">
<t hangText="Implicit Grant">
In the implicit grant, the attacker receives an access token instead of the code; the
rest of the attack works as above.
</t>
<t hangText="Mix-Up Without Interception">
A variant of the above attack works even if the first request/response pair cannot be
intercepted (for example, because TLS is used to protect these messages): Here, we
assume that the user wants to start the grant using A-AS (and not H-AS). After the
client redirected the user to the authorization endpoint at A-AS, the attacker
immediately redirects the user to H-AS (changing the client id "7ZGZldHQ"). (A vigilant
user might at this point detect that she intended to use A-AS instead of H-AS.) The
attack now proceeds exactly as in step <xref format="counter"
target="list_mixup_acg_after_authep"/> of the attack description above. <!-- I think this counter is not working properly! -->
</t>
<t hangText="Per-AS Redirect URIs">
If clients use different redirect URIs for different ASs, do not store the selected AS
in the user's session, and ASs do not check the redirect URIs properly, attackers can
mount an attack called "Cross-Social Network Request Forgery". We refer to <xref
target="oauth_security_jcs_14"/> for details.
</t>
<t hangText="OpenID Connect">
There are several variants that can be used to attack OpenID Connect. They are described
in detail in <xref target="arXiv.1704.08539" />, Appendix A, and <xref
target="arXiv.1508.04324v2" />, Section 6 ("Malicious Endpoints Attacks").
</t>
</list>
</t>
</section>
<section title="Countermeasures">
<t>In scenarios where an OAuth client interacts with multiple authorization servers, clients
MUST prevent mix-up attacks.</t>
<t>Potential countermeasures:
<list style="symbols">
<t>Configure authorization servers to return an AS identitifier (<spanx
style="verb">iss</spanx>) and the <spanx style="verb">client_id</spanx> for which a code
or token was issued in the authorization response. This enables clients to compare this
data to their own client id and the <spanx style="verb">iss</spanx> identifier of the AS
it believed it sent the user agent to. This mitigation is discussed in detail in <xref
target="I-D.ietf-oauth-mix-up-mitigation"/>. In OpenID Connect, if an ID token is
returned in the authorization response, it carries client id and issuer. It can be used
for this mitigation.</t>
<t>As it can be seen in the preconditions of the attacks above, clients can prevent mix-up
attack by (1) using AS-specific redirect URIs with exact redirect URI matching, (2)
storing, for each authorization request, the intended AS, and (3) comparing the intended
AS with the actual redirect URI where the authorization response was received.</t>
</list>
</t>
</section>
</section>
<section anchor="code_injection" title="Authorization Code Injection">
<t>In such an attack, the adversary attempts to inject a stolen authorization
code into a legitimate client on a device under his control. In the simplest
case, the attacker would want to use the code in his own client. But there
are situations where this might not be possible or intended. Examples are:
<list style="symbols">
<t>The attacker wants to access certain functions in this particular client.
As an example,
the attacker wants to impersonate his victim in a certain app or on a certain
web site.</t>
<t>The code is bound to a particular confidential client and the attacker is
unable to obtain the required client credentials to redeem the code himself.</t>
<t>The authorization or resource servers are limited to certain networks, the
attackers is unable to access directly.</t>
</list>
</t>
<t>How does an attack look like?</t>
<t>
<list style="format (%d)">
<t>The attacker obtains an authorization code by performing any of the attacks
described above.</t>
<t>It performs a regular OAuth authorization process with the legitimate client on
his device.</t>
<t>The attacker injects the stolen authorization code in the response of the
authorization server to the legitimate client.</t>
<t>The client sends the code to the authorization server's token endpoint,
along with client id, client secret and actual <spanx style="verb">redirect_uri</spanx>.</t>
<t>The authorization server checks the client secret, whether the code was issued
to the particular client and whether the actual redirect URI matches the
<spanx style="verb">redirect_uri</spanx> parameter (see <xref target="RFC6749"/>).</t>
<t>If all checks succeed, the authorization server issues access
and other tokens to the client, so now the attacker is able to impersonate
the legitimate user.</t>
</list>
</t>
<t>Obviously, the check in step (5) will fail, if the code was issued to
another client id, e.g., a client set up by the attacker. The check will also fail
if the authorization code was already redeemed by the legitimate user and was
one-time use only.</t>
<t>An attempt to inject a code obtained via a malware pretending to be the
legitimate client should also be detected, if the authorization server stored the
complete redirect URI used in the authorization request and compares it with
the redirect_uri parameter.</t>
<t><xref target="RFC6749"/>, Section 4.1.3, requires the AS to
"... ensure that the "redirect_uri"
parameter is present if the "redirect_uri" parameter was included in the initial
authorization request as described in Section 4.1.1, and if included ensure that
their values are identical.". In the attack scenario described above, the legitimate
client would use the correct redirect URI it always uses for authorization requests.
But this URI would not match the tampered redirect URI used by the attacker (otherwise,
the redirect would not land at the attackers page). So the authorization server would
detect the attack and refuse to exchange the code.</t>
<t>Note: this check could also detect attempt to inject a code, which had been obtained
from another instance of the same client on another device, if certain conditions are fulfilled:
<list style="symbols">
<t>the redirect URI itself needs to contain a nonce or another kind of one-time use,
secret data and</t>
<t>the client has bound this data to this particular instance.</t>
</list>
</t>
<t>But this approach conflicts with the idea to enforce exact redirect URI matching
at the authorization endpoint. Moreover, it has been observed that providers very often ignore the
redirect_uri check requirement at this stage, maybe because it doesn't seem to be security-critical
from reading the spec.</t>
<t>Other providers just pattern match the redirect_uri parameter against the registered
redirect URI pattern. This saves the authorization server from storing the link between the
actual redirect URI and the respective authorization code for every transaction. But this kind of
check obviously does not fulfill the intent of the spec, since the tampered redirect URI is not
considered. So any attempt to inject a code obtained using the <spanx style="verb">client_id</spanx> of a legitimate client
or by utilizing the legitimate client on another device won't be detected in the respective deployments.</t>
<t>It is also assumed that the requirements defined in <xref target="RFC6749"/>, Section 4.1.3,
increase client implementation
complexity as clients need to memorize or re-construct the correct redirect URI for the call
to the tokens endpoint.</t>
<t>This document therefore recommends to instead bind every authorization code to a certain
client instance on a certain device (or in a certain user agent) in the context of a
certain transaction.</t>
<section title="Proposed Countermeasures">
<t>There are multiple technical solutions to achieve this goal:</t>
<t>
<list hangIndent="8" style="hanging">
<t hangText="Nonce">OpenID Connect's existing <spanx style="verb">nonce</spanx>
parameter could be used for this purpose.
The nonce value is one-time use and created by the client. The client is supposed to bind
it to the user agent session and sends it with the initial request to the OpenId Provider
(OP). The OP associates the nonce to the authorization code and attests this binding in the
ID token, which is issued as part of the code exchange at the token endpoint. If an attacker
injected an authorization code in the authorization response, the nonce value in the client
session and the nonce value in the ID token will not match and the attack is detected.
The assumption is that an attacker cannot get hold of the user agent state on the victims device, where he
has stolen the respective authorization code. The main advantage of this option is that Nonce
is an existing feature used in the wild. On the other hand, leveraging Nonce by
the broader OAuth community would require AS and client to adopt ID Tokens.</t>
<t hangText="Code-bound State">The <spanx style="verb">state</spanx> parameter
as specified in <xref target="RFC6749"/> could be used similarly to
what is described above. This would require to add a further parameter
<spanx style="verb">state</spanx> to the code exchange token endpoint request.
The authorization server would then compare the <spanx style="verb">state</spanx> value it associated with
the code and the <spanx style="verb">state</spanx> value in the parameter. If those values do not match,
it is considered an attack and the request fails. The advantage of this approach
would be to utilize an existing OAuth parameter. But it would also mean to
re-interpret the purpose of <spanx style="verb">state</spanx> and to extend the token endpoint request.</t>
<t hangText="PKCE">The PKCE parameter <spanx style="verb">challenge</spanx> along
with the corresponding <spanx style="verb">verifier</spanx> as specified
in <xref target="RFC7636"/> could be used in the same way
as <spanx style="verb">nonce</spanx> or
<spanx style="verb">state</spanx>. In contrast to its original intention, the verifier
check would fail although the client uses its correct verifier but the code is
associated with a challenge, which does not match. PKCE is a deployed OAuth feature,
even though it is used today to secure native apps, only.</t>
<t hangText="Token Binding">Token binding
<xref target="I-D.ietf-oauth-token-binding"/> could also be used. In this case, the
code would need to be bound to two legs, between user agent and AS and the user
agent and the client. This requires further data (extension to response) to
manifest binding id for particular code. Token binding is promising as a
secure and convenient mechanism (due to its browser integration). As a challenge,
it requires broad browser support and use with native apps is still under
discussion.</t>
<t hangText="per instance client id/secret">One could use per instance <spanx style="verb">client_id</spanx>
and secrets and bind the code to the respective <spanx style="verb">client_id</spanx>. Unfortunately,
this does not fit into the web application programming model (would need to use
per user client ids).</t>
</list>
</t>
<t>PKCE seems to be the most obvious solution for OAuth clients as it available and
effectively used today for similar purposes for OAuth native apps whereas
<spanx style="verb">nonce</spanx> is appropriate for OpenId Connect clients.</t>
<t>Note on pre-warmed secrets: An attacker can circumvent the countermeasures
described above if he is able to create or capture the respective secret or
code_challenge on a device under his control, which is then used in the victim's
authorization request.
<vspace/>Exact redirect URI matching of authorization requests can prevent the
attacker from using the pre-warmed secret in the faked authorization transaction
on the victim's device.
<vspace/>Unfortunately, it does not work for all kinds of OAuth clients. It is
effective for web and JS apps and for native apps with claimed URLs. Attacks on
native apps using custom schemes or redirect URIs on localhost cannot be prevented
this way, except if the AS enforces one-time use for PKCE verifier or <spanx style="verb">nonce</spanx>
values.</t>
</section>
</section>
<section anchor="access_token_injection" title="Access Token Injection">
<t>In such an attack, the adversary attempts to inject a stolen access token
into a legitimate client on a device under his control. This will typically
happen if the attacker wants to utilize a leaked access token to impersonate
a user in a certain client.</t>
<t>To conduct the attack, the adversary starts an OAuth flow with the client
and modifies the authorization response by replacing the access token
issued by the authorization server or directly makes up an authorization
server response including the leaked access token. Since the response includes
the state value generated by the client for this particular transaction,
the client does not treat the response as a CSRF and will use the
access token injected by the attacker.</t>
<section title="Proposed Countermeasures">
<t>There is no way to detect such an injection
attack on the OAuth protocol level, since the token is issued without
any binding to the transaction
or the particular user agent.</t>
<t>The recommendation is therefore to use the authorization code
grant type instead of relying on response types issuing acess tokens
at the authorization endpoint. Code injection can be detected using one of
the countermeasures discussed in <xref target="code_injection"/>.</t>
</section>
</section>
<section title="Cross Site Request Forgery">
<t>An attacker might attempt to inject a request to the redirect URI of the
legitimate client on the victim's device, e.g., to cause the client to access
resources under the attacker's control.</t>
<section title="Proposed Countermeasures" anchor="csrf_countermeasures">
<t>Standard CSRF defenses should be used to protect the redirection endpoint, for example:</t>
<t>
<list hangIndent="15" style="hanging">
<t hangText="CSRF Tokens">Use of CSRF tokens which are
bound to the user agent and passed in the <spanx style="verb">state</spanx>
parameter to the authorization server.</t>
<t hangText="Origin Header">The Origin header can be
used to detect and prevent CSRF attacks. Since this
feature, at the time of writing, is not consistently
supported by all browsers, CSRF tokens should be used
in addition to Origin header checking.</t>
</list>
</t>
<t>For more details see <xref target="owasp_csrf"/>.</t>
</section>
</section>
<section title="Access Token Leakage at the Resource Server">
<t>Access tokens can leak from a resource server under certain circumstances.</t>
<section title="Access Token Phishing by Counterfeit Resource Server">
<t>An attacker may setup his own resource server and trick
a client into sending access tokens to it, which are valid for
other resource servers. If the client sends a valid access token to
this counterfeit resource server, the attacker in turn may use that
token to access other services on behalf of the resource owner.</t>
<t>This attack assumes the client is not bound to a certain
resource server (and the respective URL) at development time, but
client instances are configured with an resource server's URL at runtime.
This kind of late binding is typical in situations where the client
uses a standard API, e.g., for e-Mail, calendar, health, or banking
and is configured by an user or administrator for the standard-based
service, this particular user or company uses.</t>
<t>There are several potential mitigation strategies, which will be discussed
in the following sections.</t>
<section title="Metadata">
<t>An authorization server could provide the client with additional
information about the location where it is safe to use its access tokens. </t>
<t>In the simplest
form, this would require the AS to publish a list of its known resource
servers, illustrated in the following example using a metadata parameter
<spanx style="verb">resource_servers</spanx>:</t>
<t>
<figure>
<artwork><![CDATA[HTTP/1.1 200 OK
Content-Type: application/json
{
"issuer":"https://server.somesite.example",
"authorization_endpoint":
"https://server.somesite.example/authorize",
“resource_servers”:[
“email.somesite.example”,
”storage.somesite.example”,
”video.somesite.example”]
...
}]]></artwork>
</figure>
</t>
<t>
The AS could also return the URL(s) an access token is good
for in the token response, illustrated by the example return parameter
<spanx style="verb">access_token_resource_server</spanx>:</t>
<t>
<figure>
<artwork><![CDATA[HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
“access_token_resource_server”:
"https://hostedresource.somesite.example/path1",
...
}]]></artwork>
</figure>
</t>
<t>This mitigation strategy would rely on the client to enforce the security
policy and to only send access tokens to legitimate destinations. Results
of OAuth related security research (see for example
<xref target="oauth_security_ubc"/> and <xref target="oauth_security_cmu"/>)
indicate a large portion
of client implementations do not or fail to properly implement security controls,
like <spanx style="verb">state</spanx> checks. So relying on clients to prevent access token
phishing is likely to fail as well. Moreover given the ratio of clients to authorization
and resource servers, it is considered the more viable approach to move as much as
possible security-related logic to those entities. Clearly, the client has to
contribute to the overall security. But there are alternative countermeasures, as
described in the next sections, which provide a better balance between the involved
parties.</t>
</section>
<section anchor="pop_tokens" title="Sender Constrained Access Tokens">
<t>As the name suggests, sender constrained access token scope the applicability
of an access token to a certain sender. This sender is obliged to demonstrate
knowledge of a certain secret as prerequisite for the acceptance of that token
at a resource server.</t>
<t>A typical flow looks like this:
<list style="numbers">
<t>The authorization server associates data with the access token which binds
this particular token to a certain client. The binding can utilize the client
identity, but in most cases the AS utilizes key material (or data derived from