/
471.txt
624 lines (487 loc) · 43 KB
/
471.txt
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
[104] [DFN[[RUBYB[[[トークンエンドポイント]]]@en[token endpoint]]]]は、
[[クライアント]]に[[アクセストークン]]を発行する[[認可鯖]]上の[[エンドポイント]]です。
* 仕様書
[REFS[
- [7] [CITE@en[RFC 5849 - The OAuth 1.0 Protocol]] ([TIME[2014-12-28 14:19:21 +09:00]] 版) <http://tools.ietf.org/html/rfc5849#section-2.3>
- [34] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-3.2>
- [52] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.1.3>
- [55] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.1.4>
- [58] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.2.2>
- [61] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.3.2>
- [64] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.3.3>
- [65] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.4.2>
- [67] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.4.3>
- [68] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-4.5>
- [71] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-5.1>
- [87] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-5.2>
- [1] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-6>
- [21] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-9>
- [89] [CITE@en[RFC 6749 - The OAuth 2.0 Authorization Framework]] ([TIME[2014-12-15 14:15:35 +09:00]] 版) <http://tools.ietf.org/html/rfc6749#section-10>
- [97] [CITE[RFC Errata Report]] ([TIME[2015-02-16 00:47:02 +09:00]] 版) <http://www.rfc-editor.org/errata_search.php?rfc=6749>
- [108] [CITE@en[Final: OpenID Connect Core 1.0 incorporating errata set 1]] ([TIME[2014-11-09 04:00:29 +09:00]] 版) <http://openid.net/specs/openid-connect-core-1_0.html#TokenResponse>
- [109] [CITE@en[Final: OpenID Connect Core 1.0 incorporating errata set 1]] ([TIME[2014-11-09 04:00:29 +09:00]] 版) <http://openid.net/specs/openid-connect-core-1_0.html#ClientAuthentication>
- [170] [CITE@en[Final: OAuth Request Body Hash]] ([TIME[2009-04-12 08:08:27 +09:00]] 版) <http://oauth.googlecode.com/svn&l=52/spec/ext/body_hash/1.0/oauth-bodyhash.html#when_to_include>
]REFS]
* OAuth 1.0 トークン要求
[8] [[クライアント]]は、[[資源所有者認可]]の後、
[DFN[[RUBYB[[[トークン要求]]]@en[token request]]]]により[[トークンcredentials]]を[[鯖]]から得ることができます。
[9] [[トークン要求]]は、[[クライアントcredentials]]と
([[トークンcredentials]]のかわりに) [[一時credentials]]を使って[[認証された要求]]です
[SRC[>>7]]。
;; [CODE(URI)@en[[[oauth_token]]]] は[[一時credentials]] の[[識別子]]となります。
[10] [[トークン要求]]は、原則として[[要求メソッド]] [CODE(HTTP)@en[[[POST]]]]
を使います [SRC[>>7]]。[[鯖]]が何らかの方法で他の[[要求メソッド]]を[[広告]]した場合には、
そちらを使うこともできます [SRC[>>7]]。
[11] [[トークン要求]]は、[[鯖]]が何らかの方法で[[広告]]した[[トークン要求]]の[[エンドポイント]]を[[要求URL]]として使います [SRC[>>7]]。
;; [105] この[[エンドポイント]]ないし [[URL]] に [[OAuth 1.0]]
は特に名前を与えていませんでしたが、 [[OAuth 2.0]] の[[トークンエンドポイント]]に相当します。
[13] [[鯖]]は、[[トークン要求]]で[[保安輸送路]]を使わなければ[['''なりません''']]
[SRC[>>7]]。
[12] [[クライアント]]は、[[資源所有者認可]]の結果得られた[[検証符号]]
(を[[資源所有者]]経由で知ったもの) を [CODE(URI)@en[[[oauth_verifier]]]]
[[引数]]に指定しなければ[['''なりません''']] [SRC[>>7]]。
[132] [[Twitter]] [[xAuth]] はそのかわりに
[CODE(URI)@en[[[x_auth_password]]]],
[CODE(URI)@en[[[x_auth_username]]]],
[CODE(URI)@en[[[x_auth_mode]]]] の指定を求めています [SRC[>>131]]。
[138] [[OAuth Session Extension]] はそのかわりに
[CODE(URI)@en[[[oauth_session_handle]]]] を指定し、また[[一時credentials]]のかわりに現行の[[アクセストークン]]を使うことで、
[[アクセストークン]]の更新ができるとしています [SRC[>>137]]。
;; [139] 後の [[OAuth 2.0]] の[[更新トークン]]に相当する機能です。
[171] [[クライアント]]は [CODE(HTTP)@en[[[oauth_body_hash]]]]
[[引数]]を指定するべき[['''ではありません''']] [SRC[>>170]]。
[REFS[
- [131] [CITE[POST oauth/access_token | Twitter Developers]] ([TIME[2015-03-05 11:38:49 +09:00]] 版) <https://dev.twitter.com/oauth/reference/post/oauth/access_token>
- [137] [CITE@en[Implementers' Draft: OAuth Session 1.0 Draft 1]] ([TIME[2008-08-22 09:10:13 +09:00]] 版) <http://oauth.googlecode.com/svn/spec/ext/session/1.0/drafts/1/spec.html#update_access_token>
]REFS]
[14] [[鯖]]は、[[トークン要求]]を受信したら次の点を確認しなければ[['''なりません''']]
[SRC[>>7]]。
[FIG(list)[
- [15] [[要求]]が妥当であるか[[検証]]する
- [16] [[資源所有者]]が[[クライアント]]に[[トークンcredentials]]を与えることを[[認可]]していることを確認する
- [17] [[一時credentials]]が[[満期]]となっておらず、使用済みでもないか確認する
- [18] [[検証符号]]が正しいものか確認する
]FIG]
[19] 確認できたなら、[[状態符号]] [CODE(HTTP)[[[200]]]]、
[[MIME型]] [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
の [[payload body]] の[[応答]]とします [SRC[>>7]]。
[20] [[payload body]] には次の[[引数]]を含めなければ[['''なりません''']] [SRC[>>7]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([CODE(MIME)@en[[[application/x-www-form-urlencoded]]]])
]FIGCAPTION]
:[CODE(URI)@en[[[oauth_token]]]]:[[トークン識別子]]
:[CODE(URI)@en[[[oauth_token_secret]]]]:[[トークン共有秘密]]
]FIG]
[136] [[OAuth Session Extension]] は更に次の[[引数]]を追加しています。
[FIG(short list)[
- [CODE(HTTP)@en[[[oauth_session_handle]]]]
- [CODE(HTTP)@en[[[oauth_authorization_expires_in]]]]
- [CODE(HTTP)@en[[[oauth_expires_in]]]]
]FIG]
[169] [[はてな]]は更に次の[[引数]]を追加しています [SRC[>>168]]。
[FIG(short list)[
- [CODE(URI)@en[[[display_name]]]]
- [CODE(URI)@en[[[url_name]]]]
]FIG]
[REFS[
- [168] [CITE[Consumer key を取得して OAuth 開発をはじめよう - Hatena Developer Center]] ([TIME[2015-03-05 19:09:33 +09:00]] 版) <http://developer.hatena.ne.jp/ja/documents/auth/apis/oauth/consumer>
]REFS]
[135] [[OAuth 1.0]] 本体仕様としてはエラー時の応答については規定していません。
[[OAuth Problem Reporting Extension]] は報告方法を規定しており、
実装によってはこれに対応しています。
* OAuth 2.0 トークンエンドポイント
[35] [[認可鯖]]の[DFN[[RUBYB[[[トークンエンドポイント]]]@en[token endpoint]]]]は、
[[クライアント]]が[[認可承諾]]や[[更新トークン]]を使って[[アクセストークン]]を得るために使うものです。
[[トークンエンドポイント]]は、
[[暗示的承諾型]]以外の[[承諾型]] ([[認可符号]]、[[資源所有者合言葉credentials]]、
[[クライアントcredentials]]) で使います。 [SRC[>>34]]
** トークンエンドポイントへの要求
[36] [[クライアント]]が[[トークンエンドポイント]]の位置を知る方法は [[OAuth]]
の仕様の範囲外とされていますが、普通は[[サービス]]の[[ドキュメント]]で示されます [SRC[>>34]]。
[38] [[トークンエンドポイント]]は [[TLS]] を使わなければ[['''なりません''']] [SRC[>>34, >>89]]。
[[アクセストークン]]、[[更新トークン]]を転送する場合は [[HTTPS鯖認証]]を使わなければ[['''なりません''']] [SRC[>>89]]。
[[クライアント]]は [[RFC 6125]] により[[認可鯖]]の[[TLS証明書]]を検証し[[鯖]]の
[[identity]] を[[認証]]しなければ[['''なりません''']] [SRC[>>89]]。
[37] [[トークンエンドポイント]]の [[URL]] は
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] 形式の [[query]]
を含んでも構いません。[[素片識別子]]を含んでは[['''なりません''']]。
[[query]] が含まれる場合、[[引数]]を追加するときにはそのまま残さなければ[['''なりません''']]。
[SRC[>>34]]
[48] [[クライアント]]は、[[認可符号]]から[[アクセストークン]]を得るために[[トークンエンドポイント]]に[[要求]]を送信する場合、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
により次の[[引数]]を指定します [SRC[>>52]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([CODE(MIME)@en[[[application/x-www-form-urlencoded]]]])
]FIGCAPTION]
:[CODE(URI)@en[[[grant_type]]]]:[CODE(URI)@en[[[authorization_code]]]]
でなければ[['''なりません''']] [SRC[>>52]]。
:[CODE(URI)@en[[[code]]]]:受信した[[認可符号]]を指定しなければ[['''なりません''']] [SRC[>>52]]。
:[CODE(URI)@en[[[redirect_uri]]]]:[[認可エンドポイント]]への要求で
[CODE(URI)@en[[[redirect_uri]]]] [[引数]]を指定した場合は、同じ値を指定しなければ[['''なりません''']]
[SRC[>>52]]。
:[CODE(URI)@en[[[client_id]]]]:[[クライアント認証]]しない場合は指定しなければ[['''なりません''']] [SRC[>>52, >>34]]。
]FIG]
[120] [[Azure]] は [CODE(URI)@en[[[resource]]]] [[引数]]を追加しています [SRC[>>119]]。
[150] [[Salesforce]] は [CODE(URI)@en[[[code_verifier]]]], [CODE(URI)@en[[[format]]]]
を追加しています [SRC[>>149]]。
[REFS[
- [119] [CITE@en[Authorization Code Grant Flow]] ([TIME[2015-03-05 10:35:42 +09:00]] 版) <https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx>
- [149] [CITE[Understanding the Web Server OAuth Authentication Flow]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_web_server_oauth_flow.htm>
]REFS]
[50] [[クライアント]]は、[[資源所有者]]の [[credentials]] から[[アクセストークン]]を得るため
([[資源所有者合言葉credentials]]フロー) に[[トークンエンドポイント]]に[[要求]]を送信する場合、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
により次の[[引数]]を指定します [SRC[>>61]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([CODE(MIME)@en[[[application/x-www-form-urlencoded]]]])
]FIGCAPTION]
:[CODE(URI)@en[[[grant_type]]]]:[CODE(URI)@en[[[password]]]]
でなければ[['''なりません''']] [SRC[>>61]]。
:[CODE(URI)@en[[[username]]]]:[[資源所有者]]の[[利用者名]]を指定しなければ[['''なりません''']] [SRC[>>61]]。
:[CODE(URI)@en[[[password]]]]:[[資源所有者]]の[[合言葉]]を指定しなければ[['''なりません''']]
[SRC[>>61]]。
:[CODE(URI)@en[[[scope]]]]:アクセス要求の[[適用範囲]]を指定できます [SRC[>>61]]。
]FIG]
[66] [[クライアント]]は、[[クライアントcredentials]] から[[アクセストークン]]を得るため
([[クライアントcredentials]]フロー) に[[トークンエンドポイント]]に[[要求]]を送信する場合、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
により次の[[引数]]を指定します [SRC[>>65]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([CODE(MIME)@en[[[application/x-www-form-urlencoded]]]])
]FIGCAPTION]
:[CODE(URI)@en[[[grant_type]]]]:[CODE(URI)@en[[[client_credentials]]]]
でなければ[['''なりません''']] [SRC[>>65]]。
:[CODE(URI)@en[[[scope]]]]:アクセス要求の[[適用範囲]]を指定できます [SRC[>>65]]。
]FIG]
[125] [[Azure]] は [CODE(URI)@en[[[resource]]]] [[引数]]を追加しています [SRC[>>124]]。
[146] [[reddit]] は場合によって [CODE(URI)@en[[[grant_type]]=[[https://oauth.reddit.com/grants/installed_client]]]]
を使います。また [CODE(URI)@en[[[device_id]]]] [[引数]]を追加しています。 [SRC[>>145]]
[REFS[
- [124] [CITE@en[Service to Service Calls Using Client Credentials]] ([TIME[2015-03-05 10:43:44 +09:00]] 版) <https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx>
- [145] [CITE@en[OAuth2 · reddit/reddit Wiki]] ([TIME[2015-03-05 16:39:22 +09:00]] 版) <https://github.com/reddit/reddit/wiki/OAuth2#user-content-application-only-oauth>
]REFS]
[2] [[クライアント]]は、[[更新トークン]] から[[アクセストークン]]を得るために[[トークンエンドポイント]]に[[要求]]を送信する場合、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[payload body]]
により次の[[引数]]を指定します [SRC[>>1]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([CODE(MIME)@en[[[application/x-www-form-urlencoded]]]])
]FIGCAPTION]
:[CODE(URI)@en[[[grant_type]]]]:[CODE(URI)@en[[[refresh_token]]]]
でなければ[['''なりません''']] [SRC[>>1]]。
:[CODE(URI)@en[[[refresh_token]]]]:[[クライアント]]に発行されている[[更新トークン]]を指定しなければ[['''なりません''']] [SRC[>>1]]。
:[CODE(URI)@en[[[scope]]]]:アクセス要求の[[適用範囲]]を指定できます [SRC[>>1]]。
元々[[資源所有者]]に[[承諾]]された[[適用範囲]]以外を指定しては[['''なりません''']] [SRC[>>1]]。
省略すると、元々[[資源所有者]]に[[承諾]]された[[適用範囲]]を表します [SRC[>>1]]。
]FIG]
[122] [[Azure]] は [CODE(URI)@en[[[resource]]]] [[引数]]を追加しています [SRC[>>119]]。
[158] [[Salesfoce]] は [CODE(URI)@en[[[format]]]] [[引数]]を追加しています [SRC[>>157]]。
[69] [[クライアント]]は、拡張の[[承諾型]]の規定に従い[[トークンエンドポイント]]に[[要求]]を送信する場合、
[CODE(URI)@en[[[grant_type]]]] [[引数]]に[[絶対URL]]を指定し、
必要に応じて追加の[[引数]]も指定します [SRC[>>68]]。
[EG[
[70] 例えば [[SAML 2.0]] が拡張の[[承諾型]]を規定しています。
]EG]
[EG[
[113] 例えば [[JWT]] を使う場合、
[CODE(URI)@en[[[grant_type]]=[[urn:ietf:params:oauth:grant-type:jwt-bearer]]]]
と [CODE(URI)@en[[[assertion]]]] [[引数]]を指定します。
[114] [[Google]] がこれを実装している [SRC[>>115]] ようです。
[REFS[
- [115] [CITE@ja[Using OAuth 2.0 for Server to Server Applications - Google Accounts Authentication and Authorization — Google Developers]] ([TIME[2015-02-04 03:07:26 +09:00]] 版) <https://developers.google.com/accounts/docs/OAuth2ServiceAccount>
]REFS]
]EG]
[EG[
[116] [[Google]] は [[OAuth 1.0]] から [[OAuth 2.0]] への移行のために
[CODE(URI)@en[[[grant_type]]=[[urn:ietf:params:oauth:grant-type:migration:oauth1]]]]
を提供していました。 [[OAuth 2.0]] [[クライアント認証]]、 [[OAuth 1.0]] による
[[HTTP認証]]、省略可能な [CODE(URI)@en[[[scope]]]] [[引数]]を指定することで、
[[更新トークン]]を得ることができるものです。
;; [CODE(URI)@en[[[urn:ietf:params:oauth:grant-type:migration:oauth1]]]] 参照。
]EG]
[EG[
[165] [[Facebook]] の [CODE(URI)@en[[[grant_type]]=[[fb_exchange_token]]]]
は [CODE(URI)@en[[[fb_exchange_token]]]] [[引数]]を使っています [SRC[>>164]]。
]EG]
;; [123] [[Azure]] は [CODE(URI)@en[[[grant_type]]]] という名前で
[CODE(URI)@en[[[response_type]]]] [[引数]]に相当するものを指定させています [SRC[>>119, >>124]]。
[41] [[要求]]の[[引数]]は、複数指定しては[['''なりません''']] [SRC[>>34]]。
[160] [[SurveyMonkey]] は [[payload body]] ではなく [[URL query]] に
[CODE(URI)@en[[[api_key]]]] [[引数]]を指定することを求めています [SRC[>>159]]。
[REFS[
- [159] [CITE@en[SurveyMonkey - Guide OAuth]] ([TIME[2015-03-05 17:23:37 +09:00]] 版) <https://developer.surveymonkey.com/mashery/guide_oauth>
- [161] [CITE[Connecting]] ([TIME[2015-03-05 17:39:49 +09:00]] 版) <https://developer.foursquare.com/overview/auth>
- [164] [CITE@ja[Access Tokens]] ([TIME[2015-03-05 18:03:06 +09:00]] 版) <https://developers.facebook.com/docs/facebook-login/access-tokens>
]REFS]
[39] [[クライアント]]は[[トークンエンドポイント]]への[[要求]]で [CODE(HTTP)@en[[[POST]]]]
[[要求メソッド]]を使わなければ[['''なりません''']] [SRC[>>34]]。
[162] [[Facebook]] [SRC[>>164]] や [[fouresquare]] [SRC[>>161]]
は [CODE(HTTP)@en[[[GET]]]] を使っているようです。
** クライアント認証
[43] [[クライアント型]]が[[機密]]の[[クライアント]]と、
[[クライアントcredentials]]を発行された[[クライアント]]は、
[[トークンエンドポイント]]への[[要求]]で[[クライアント認証]]を行わなければ[['''なりません''']]
[SRC[>>34, >>52, >>61, >>65, >>1]]。
ただし[[ネイティブアプリケーション]]は、
[[認可符号]]フローにおいて[[クライアント]]の [[credentials]]
を送信する[['''べきではありません''']] [SRC[>>21]]。
[49] [[クライアント型]]が[[公開]]の[[クライアント]]は、(以上に該当しなくても)
[[トークンエンドポイント]]への[[要求]]で自身を識別する
[CODE(URI)@en[[[client_id]]]] [[引数]]を使っても構いません [SRC[>>34, >>97]]。
;; この場合は [[credentials]] は指定しないので、[[クライアント認証]]は行われません。
[82] [[認可鯖]]は、[[クライアント型]]が[[機密]]の[[クライアント]]や[[クライアントcredentials]]
を発行した[[クライアント]]に関しては、
[[トークンエンドポイント]]における [[OAuth 2.0]] の各[[承諾型]]の要求において、
[[クライアント認証]]を必須としなければ[['''なりません''']] [SRC[>>52, >>61, >>65, >>1, >>89]]。
[22] [[認可鯖]]は、[[クライアント型]]が[[機密]]の[[クライアント]]については、
自身の要件次第で任意の[[認証]]方式を使って[[認証]]して構いません [SRC[>>7]]。
[[認可鯖]]は、[[クライアント型]]が[[公開]]の[[クライアント]]についても[[認証]]して構いませんが、
[[クライアント]]の識別のためにこれに依存しては[['''なりません''']] [SRC[>>7]]。
;; [24] 一般的には[[合言葉]]や、[[公開鍵]]と[[秘密鍵]]の組のようなものを[[認可鯖]]が発行または登録して使います [SRC[>>7]]。[[クライアントの登録]]も参照。
[25] [[認可鯖]]は、
[[トークンエンドポイント]]における [[OAuth 2.0]] の各[[承諾型]]の要求に[[クライアント認証]]が含まれていれば、[[認証]]しなければ[['''なりません''']]
[SRC[>>52, >>61, >>65, >>1]]。
;; [23] [[OAuth 2.0クライアント認証]]は[[クライアント]]と[[認可鯖]]の間の任意の[[エンドポイント]]で利用可能な形で規定されてはいますが、実際に利用されるのは[[トークンエンドポイント]]でのみです。
[26] 複数の[[認証]]方法を単独の[[要求]]で併用しては[['''なりません''']] [SRC[>>7]]。
[110] [[OAuth 2.0]] としては[[認証]]方式に特に名前を与えていませんが、
[[OpenID Connect]] は名前を定義 [SRC[>>109]] しています。次の[[認証]]方式があります。
[FIG(short list)[
- [CODE@en[[[client_secret_basic]]]]
- [CODE@en[[[client_secret_post]]]]
- [CODE@en[[[client_secret_jwt]]]]
- [CODE@en[[[private_key_jwt]]]]
- [CODE@en[[[none]]]]
]FIG]
[111] [DFN[[CODE@en[[[none]]]]]] は、[[クライアント認証]]なしを表します [SRC[>>109]]。
[27] [[認可鯖]]は、[[合言葉]]で[[認証]]する時は、 [[TLS]] を要求しなければ[['''なりません''']]
[SRC[>>7, >>89]]。また[[総当たり攻撃]]に対して[[エンドポイント]]を保護しなければ[['''なりません''']]
[SRC[>>7]]。
[28] [RUBYB[[[合言葉]]]@en[password]]を使う場合、[[基本認証]]を使って構いません。
[[クライアント]]に[[合言葉]]を発行した[[認可鯖]]は、[[基本認証]]に対応しなければ[['''なりません''']]。
[SRC[>>7]]
;; [118] [[Google]] と [[Facebook]] [SRC[>>164]]、 [[GitHub]] [SRC[>>166]]
その他いくつかの[[サービス]] [SRC[>>119, >>133, >>142, >>147, >>159, >>163]]
は、少なくても[[ドキュメント]]に明記されている範囲では、
[[引数]]を使う方法のみ対応していて、[[基本認証]]には対応していないようです。
;; [130] [[Twitter]] [SRC[>>129]] や [[reddit]] [SRC[>>144]]
は[[基本認証]]にのみ対応しているようです。
;; [141] [[Spotify]] は[[基本認証]]を原則とし、[[引数]]を使う方法にも対応しています
[SRC[>>140]]。
;; [174] [[Bitly]] は[[認可符号]]フローにおいては[[引数]]を使う方法のみ記載し、
[[資源所有者合言葉credentials]]フローにおいては[[基本認証]]のみ記載しています [SRC[>>172]]。
なお [[Bitly]] は[[トークンエンドポイント]]において[[基本認証]]のみ、
または[[基本認証]]と [CODE(URI)@en[[[client_id]]]] および [CODE(URI)@en[[[client_secret]]]]
の指定によって[[アクセストークン]]を取得する独自のフローを実装しており [SRC[>>172]]、
その場合[[基本認証]]は[[資源所有者]]の[[利用者名]]と[[合言葉]]になります。
;; [155] [[Salesforce]] は[[引数]]を使う方法と、 [[JWT]] を使う方法に対応しています
[SRC[>>154, >>153]]。
[REFS[
- [166] [CITE@en[OAuth | GitHub API]] ([TIME[2015-03-05 18:02:01 +09:00]] 版) <https://developer.github.com/v3/oauth/>
- [129] [CITE[Application-only authentication | Twitter Developers]] ([TIME[2015-03-05 10:58:24 +09:00]] 版) <https://dev.twitter.com/oauth/application-only>
- [133] [CITE[1. OAuth認証 - ヤマレコ Web API]] ([TIME[2015-02-25 16:41:06 +09:00]] 版) <https://sites.google.com/site/apiforyamareco/api/oauth>
- [140] [CITE@en-US[Web API Authorization Guide - Spotify Developer]] ([TIME[2015-03-05 15:59:09 +09:00]] 版) <https://developer.spotify.com/web-api/authorization-guide/>
- [142] [CITE@en[OAuth | Slack]] ([[Slack]] 著, [TIME[2015-03-05 16:04:09 +09:00]] 版) <https://api.slack.com/docs/oauth>
- [144] [CITE@en[OAuth2 · reddit/reddit Wiki]] ([TIME[2015-03-05 16:29:00 +09:00]] 版) <https://github.com/reddit/reddit/wiki/OAuth2#user-content-token-retrieval-code-flow>
- [147] [CITE@ja[• Instagram Developer Documentation]] ([TIME[2015-03-05 16:42:50 +09:00]] 版) <https://instagram.com/developer/authentication/>
- [154] [CITE[Understanding the Web Server OAuth Authentication Flow]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_web_server_oauth_flow.htm>
- [153] [CITE[Understanding the Username-Password OAuth Authentication Flow]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_username_password_oauth_flow.htm>
- [163] [CITE@en[Authenticating with OAuth 2.0 | LinkedIn Developer Network]] ([TIME[2015-03-05 17:56:22 +09:00]] 版) <https://developer.linkedin.com/docs/oauth2>
- [172] [CITE[Bitly API Documentation]] ([TIME[2014-11-01 00:33:47 +09:00]] 版) <http://dev.bitly.com/authentication.html>
]REFS]
[29] [[基本認証]]を使う場合、[[利用者名]]は[[クライアント識別子]]を [[UTF-8]] で
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[符号化]]したもの、
[[合言葉]]は[[クライアント]]の[[合言葉]]を [[UTF-8]] で
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] [[符号化]]したものとします。
[SRC[>>7]] これを [DFN[[CODE@en[[[client_secret_basic]]]]]] と呼びます [SRC[>>109]]。
;; [30] 入力が名前と値の組でないわけですが、
[CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
版[[パーセント符号化]]を使うという意味だと思われます。
[31] なぜか[[認可鯖]]側の解釈の方法は規定されていません。
;; [32] どの[[文字]]が[[パーセント符号化]]されるのか [[RFC]] および参照先の [[HTML4]]
では曖昧なので、[[鯖]]は一旦[[復号]]してから比較する必要がありそうです。
[33] [[認可鯖]]は、 [[payload body]] に[[引数]]を指定する方式に対応しても構いません。
しかし[[クライアント]]は[[基本認証]]を使えない場合のみこの方法を使う[['''べきです''']]。
[[payload body]] でなく[[要求URL]]中で指定しては[['''なりません''']]。 [SRC[>>7]]
これを [DFN[[CODE@en[[[client_secret_post]]]]]] と呼びます [SRC[>>109]]。
[59] その場合、[[クライアント]]は [CODE(URI)@en[[[client_id]]]] [[引数]]に[[クライアント識別子]]を、
[CODE(URI)@en[[[client_secret]]]] [[引数]]に[RUBYB[クライアント秘密]@en[client secret]]を指定しなければ[['''なりません''']]。
ただし[[クライアント秘密]]が[[空文字列]]なら、 [CODE(URI)@en[[[client_secret]]]]
[[引数]]は省略できます。 [SRC[>>7]]
;; [57] [CODE(URI)@en[[[client_secret]]]] [[引数]]の構文上の制約により、
この方法を使うなら[[合言葉]]に含められるのは[[印字可能ASCII文字]]に限られます。
[60] [[認可鯖]]は他の[[HTTP認証]]方式に対応しても構いませんが、
[[クライアント識別子]]と当該認証方式との対応関係を定義しなければ[['''なりません''']]
[SRC[>>7]]。
[112] [[OpenID Connect]] は [[JWT]] 形式で [CODE(URI)@en[[[client_assertion]]]]
[[引数]]と [CODE(URI)@en[[[client_assertion_type]]]] [[引数]]を指定する[[クライアント認証]]方式を2通り規定しています。
[90] [[認可鯖]]は、[[Webアプリケーション]]たる[[クライアント]]に関して[[合言葉]]よりも強い[[認証]]手段を検討することが[RUBYB[推奨]@en[encourage]]されています。
[[Webアプリケーション]]は[[合言葉]]その他の [[credentials]] の[[機密]]性を維持しなければ[['''なりません''']]。 [SRC[>>89]]
[81] [[認可鯖]]は、[[ネイティブアプリケーション]]や[[利用者エージェントベースのアプリケーション]]である[[クライアント]]に[[クライアント認証]]用の[[合言葉]]その他の
[[credentials]] を発行しては[['''なりません''']]。ただし[[ネイティブアプリケーション]]を特定の[[装置]]上で動作させたものに対しては[[合言葉]]その他の [[credentials]]
を発行しても構いません。 [SRC[>>89]]
[94] [[認可鯖]]は、推測による攻撃を防がなければ[['''なりません''']]。
生成された[[トークン]]の場合、
攻撃者が推測できる確率は 2[SUP[-128]] [[以下]]で[['''なければならず''']]、
2[SUP[-160]] [[以下]]である[['''べきです''']]。
そうでない[[末端利用者]]が扱う[[credentials]]の場合でも、
何らかの方法で保護しなければ[['''なりません''']]。 [SRC[>>89]]
[91] [[認可鯖]]は、[[クライアント認証]]が不可能な時に、
[[クライアント]]の [[identity]] を[RUBYB[検証]@en[validate]]する他の手段を用いる[['''べき''']]です。
例えば、[[リダイレクトURL]]を登録させたり、[[資源所有者]]に協力させたりできます。
[[認可鯖]]は、性質上[[認証]]できない[[クライアント]]については[[リダイレクトURL]]
の登録を求めなければ[['''なりません''']]。それ以外でも不正な[[クライアント]]から[[資源所有者]]を保護する方策をとる[['''べきです''']]。
[[リダイレクトURL]]が正しいからといって[[クライアント]]の [[identity]]
の検証には不十分ではありますが、 [[credentials]] を不正な[[クライアント]]に渡してしまうことは防止できます。 [SRC[>>89]]
[92] [[認可鯖]]は認証していない[[クライアント]]とのやりとりの[[セキュリティー]]を勘案し、
[[更新トークン]]など他の [[credentials]] を渡さないなど注意しなければなりません [SRC[>>89]]。
;; [44] [[認可鯖]]は[[クライアント認証]]を次の目的で使います [SRC[>>34]]。
[FIG(list)[
- [45] [[更新トークン]]や[[認可符号]]とその発行先の[[クライアント]]との紐付け。
[[認可符号]]を安全でない[[通信路]]で[[リダイレクトエンドポイント]]に送る時や[[リダイレクトURL]]
が完全に登録されていない時には特に重要です。
- [46] [[クライアント]]を無効化したり、[[credentials]] を変更したりして、
[[更新トークン]]が漏洩した時に濫用を防止。[[更新トークン]]をすべて変更するよりはこちらの方が容易です。
- [47] [[credentials]] の定期的な[RUBYB[入れ替え]@en[rotation]]を含む[[認証]]管理で良いとされている慣習の実行。
[[更新トークン]]をすべて入れ替えるのは大変ですが、[[クライアントcredentials]]一式だけならずっと容易です。
]FIG]
;; [93] [[認可エンドポイント]]も参照。
[98] なおこの[[クライアント認証]]は、[[トークンエンドポイント]]の他、
[[revokeエンドポイント]]でも使われます。
;; [103] 本項の[[クライアント認証]]は、 [[SSLクライアント認証]]とは関係ありません。
** トークンエンドポイントの処理
[83] [[認可鯖]]は、認識できない[[引数]]を無視しなければ[['''なりません''']] [SRC[>>34]]。
[40] [[要求]]の[[引数]]に値が含まれなければ、指定されなかったものと扱わなければ[['''なりません''']] [SRC[>>34]]。
;; [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]] で [CODE[[[=]]]]
が含まれない場合を指しているのでしょうか? [[空文字列]]が指定された場合と区別する必要があるということでしょうか??
[54] [[認可鯖]]は、[[認可符号]]から[[アクセストークン]]の発行を求められている場合、
[[認可符号]]が妥当なものであることを確認しなければ[['''なりません''']] [SRC[>>52]]。
[[認可符号]]は1回しか使えません。
[100] 攻撃者は大量の[[要求]]で[[クライアント]]に適当な[[認可符号]]を与え、[[認可鯖]]にアクセスさせることで、
間接的に[[認可鯖]]の[[HTTP接続]]を枯渇させる [[DoS攻撃]]を試みるかもしれません。
[[認可鯖]]には攻撃者の情報がほとんど届かず、対策が難しい攻撃です。
[[認可鯖]]は不適切な[[認可符号]]があまりに多い[[クライアント]]には[[誤り]]応答を返すべきかもしれません [SRC[>>99]]。
[REFS[
- [99] [CITE@en[RFC 6819 - OAuth 2.0 Threat Model and Security Considerations]] ([TIME[2015-02-10 06:43:00 +09:00]] 版) <http://tools.ietf.org/html/rfc6819#section-4.4.1.12>
]REFS]
[53] [[認可鯖]]は、[[認可符号]]から[[アクセストークン]]の発行を求められている場合、
[[クライアント型]]が[[機密]]の[[クライアント]]に対するものであるか、
[[クライアント型]]が[[公開]]の[[クライアント]]に対するもので[[認可符号]]の発行先と
[CODE(URI)@en[[[client_id]]]] が合致していることを確認しなくては[['''なりません''']] [SRC[>>52, >>89]]。
[102] 攻撃対象の[[クライアント]]がいわゆる[[OAuthログイン]]を実装している場合において、攻撃者の有する[[クライアント]]に攻撃対象の[[資源所有者]]を誘導して[[認可符号]]を取得し、その[[認可符号]]を攻撃対象の[[クライアント]]に与えることで、攻撃者が攻撃対象[[クライアント]]における攻撃対象[[資源所有者]]になりすまして[[ログイン]]できてしまいます [SRC[>>101]]。
[[公開]]の[[クライアント]]に関してこれを防ぐことはできません。
[REFS[
- [101] [CITE@en[RFC 6819 - OAuth 2.0 Threat Model and Security Considerations]] ([TIME[2015-02-10 06:43:00 +09:00]] 版) <http://tools.ietf.org/html/rfc6819#section-4.4.1.13>
]REFS]
[54] [[認可鯖]]は、[[認可符号]]から[[アクセストークン]]の発行を求められている場合、
[[認可エンドポイント]]へのアクセス時に [CODE(URI)@en[[[redirect_uri]]]]
[[引数]]が指定されていたなら本要求にも [CODE(URI)@en[[[redirect_uri]]]]
[[引数]]が含まれており、両者の値が一致することを確認しなければ[['''なりません''']]
[SRC[>>52, >>89]]。
[62] [[認可鯖]]は、[[資源所有者]]の [[credentials]] から[[アクセストークン]]の発行を求められている場合、
指定された [[credentials]] を検証しなければ[['''なりません''']] [SRC[>>52]]。
[3] [[認可鯖]]は、[[更新トークン]]から[[アクセストークン]]の発行を求められている場合、
指定された[[更新トークン]]を検証しなければ[['''なりません''']] [SRC[>>1]]。
[[クライアント認証]]可能であれば、正しい[[クライアント]]か検証しなければ[['''なりません''']]
[SRC[>>89]]。
[63] [[認可鯖]]は、回数制限や警告などにより、[[資源所有者合言葉credentials]]
の[[総当たり攻撃]]から[[エンドポイント]]を保護しなければ[['''なりません''']] [SRC[>>52]]。
[95] [[認可鯖]]は [[CSRF]] 対策が必要です。[[資源所有者]]の [[credentials]]
を第三者に漏らしてしまう形の攻撃は難しそうですが、[[認可鯖]] (や間接的に[[クライアント]])
に対する [[DoS攻撃]]や、 [[CSRF]] を引き起こされた被害者たる
[[Webブラウザー]]の利用者への嫌がらせには使えるかもしれません。
;; [96] その性質上、[[CSRF]] 対策用のトークンを指定させるような方法は使えません。
[CODE(HTTP)@en[[[Origin:]]]] [[ヘッダー]]の値と[[クライアント]]の登録情報を比較して不適切な[[要求]]を検出するのがよいでしょうか。
** トークンエンドポイントの応答
[56] [[認可鯖]]は、[[アクセストークン]]の発行を求められている場合、
要求が妥当であり[[認可]]されたなら、[[アクセストークン]]を発行します
[SRC[>>55, >>64, >>67, >>68, >>1]]。
[4] [[認可符号]]や[[資源所有者合言葉credentials]]、拡張の[[承諾型]]では、
[[更新トークン]]も発行することもできます [SRC[>>55, >>64, >>68]]。
ただし[[クライアント認証]]していない場合には発行するべきではないかもしれません [SRC[>>89]]。
[5] [[クライアントcredentials]]では、
[[更新トークン]]を発行する[['''べきではありません''']] [SRC[>>67]]。
[6] [[更新トークン]]から[[アクセストークン]]を求めている場合には、
新しい[[更新トークン]]を発行しても構いません。その[[適用範囲]]
([[scope]]) は元の[[更新トークン]]と同じでなければ[['''なりません''']]。
その場合には[[認可鯖]]は古い[[更新トークン]]を取り消し ([[revoke]])
して構いませんし、[[クライアント]]は古い[[更新トークン]]を破棄しなければ[['''なりません''']]。
[SRC[>>1]]
[72] その場合には、 [CODE(HTTP)[[[200]]]] [[応答]]で次の[[引数]]を
[[JSON]] ([CODE(MIME)@en[[[application/json]]]]) [[payload body]] の
[[JSONオブジェクト]]の名前と値 ([[文字列]]なら [[JSON文字列]]、
[[数値]]なら [[JSON数値]]) に含めます [SRC[>>71]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([[JSONオブジェクト]])
]FIGCAPTION]
:[73] [CODE(HTTP)@en[[[access_token]]]]:[[認可鯖]]が発行した[[アクセストークン]]を指定しなければ[['''なりません''']] [SRC[>>71]]。
:[74] [CODE(HTTP)@en[[[token_type]]]]:発行した[[トークン]]の種類を指定しなければ[['''なりません''']]
[SRC[>>71]]。
:[75] [CODE(HTTP)@en[[[expires_in]]]]:[[アクセストークン]]の[[寿命]]を[[秒]]単位で指定する[['''べきです''']] [SRC[>>71]]。
:[76] [CODE(HTTP)@en[[[refresh_token]]]]:同じ[[認可承諾]]を使って新しい[[アクセストークン]]を得られる[[更新トークン]]を指定できます [SRC[>>71]]。
:[77] [CODE(HTTP)@en[[[scope]]]]:[[クライアント]]が要求した[[適用範囲]]と[[アクセストークン]]の[[適用範囲]]が異なるなら、指定しなければ[['''なりません''']]。同じ場合も指定できます。 [SRC[>>71]]
:[107] [CODE(HTTP)@en[[[id_token]]]]:[[OpenID Connect]] の場合には指定しなければ[['''なりません''']] [SRC[>>108]]。
]FIG]
;; [78] どれが文字列でどれが数値かは明確ではありませんが、
[CODE(HTTP)@en[[[expires_in]]]] は[[数値]]、それ以外は[[文字列]]と思われます。
[106] [[アクセストークン型]]によっては、更に追加の[[引数]]を指定する必要があるかもしれません。
;; [[アクセストークン型]]を参照。
[117] [CODE(URI)@en[[[grant_type]]=[[urn:ietf:params:oauth:grant-type:migration:oauth1]]]]
では、 [CODE(URI)@en[[[refresh_token]]]] ([[更新トークン]]) のみが返されることになっていました。
[121] [[Azure]] は [CODE(URI)@en[[[resource]]]] [[引数]]と
[CODE(URI)@en[[[expires_on]]]] [[引数]]を追加しています [SRC[>>119]]。
[134] [[ヤマレコ]]は [CODE(URI)@en[[[token_type]]]] [[引数]]を指定せず、
成功時でも [CODE[[[error]]]] [[引数]]と [CODE[[[error_message]]]]
[[引数]] (独自) を指定するようです [SRC[>>133]]。
[148] [[Instagram]] は [CODE(URI)@en[[[token_type]]]] [[引数]]を指定せず、
[CODE(URI)@en[[[user]]]] [[引数]] (独自) を指定するようです [SRC[>>147]]。
;; [CODE(URI)@en[[[user]]]] の値は [[JSONオブジェクト]]です。
[173] [[Bitly]] は [CODE@en[[[apiKey]]]] [[引数]] (独自) を指定するようです。
ただし非推奨で削除予定とあります。 [SRC[>>172]] [TIME[2015-03-05T16:02:49.500Z]]
[143] [[foursquare]] など [SRC[>>161, >>163, >>142, >>172]] は [CODE(URI)@en[[[token_type]]]] [[引数]]を指定しないようです。
[152] [[Salesforce]] は [CODE(URI)@en[[[token_type]]]] [[引数]]を指定しないようです。
独自の [CODE(URI)@en[[[id]]]], [CODE(URI)@en[[[instance_url]]]],
[CODE(URI)@en[[[issued_at]]]], [CODE(URI)@en[[[signature]]]] を指定するようです。 [SRC[>>149, >>156, >>157]]
[151] [[Salesforce]] は[[要求]]で [CODE(URI)@en[[[format]]]] [[引数]]を指定した場合に[[応答]]が他の[[MIME型]]になるようです [SRC[>>149, >>157]]。
[167] [[GitHub]] は[[要求]]で [CODE(HTTP)@en[[[Accept:]]]] を指定した場合に[[応答]]が他の
[[MIME型]]になるようです。既定値は [CODE(MIME)@en[[[application/x-www-form-urlencoded]]]]
になっているようです。 [SRC[>>166]]
[42] [[応答]]の[[引数]]は、複数指定しては[['''なりません''']] [SRC[>>34]]。
[79] 更に、 [CODE(HTTP)@en[[[Cache-Control:]] [[no-store]]]] と
[CODE(HTTP)@en[[[Pragma:]] [[no-cache]]]] を含めなければ[['''なりません''']] [SRC[>>71]]。
[80] [[クライアント]]は、認識できない名前の[[引数]]を無視しなければ[['''なりません''']]
[SRC[>>71]]。
[56] [[認可鯖]]は、[[アクセストークン]]の発行を求められている場合、
[[クライアント認証]]に失敗したか要求が非妥当であったなら、
誤り応答を返します [SRC[>>55, >>64, >>67, >>68, >>1]]。
[88] その場合には、 [CODE(HTTP)[[[400]]]] [[応答]]で次の[[引数]]を
[[JSON]] ([CODE(MIME)@en[[[application/json]]]]) [[payload body]] の
[[JSONオブジェクト]]の名前と値 ([[文字列]]なら [[JSON文字列]]、
[[数値]]なら [[JSON数値]]) に含めます [SRC[>>87]]。
[FIG(list members)[
[FIGCAPTION[
[[payload body]] ([[JSONオブジェクト]])
]FIGCAPTION]
:[84] [CODE(URI)@en[[[error]]]]:[[誤り符号]]を指定しなければ[['''なりません''']] [SRC[>>87]]。
:[85] [CODE(URI)@en[[[error_description]]]]:[[人間可読]]な[[誤り]]の説明を指定して構いません
[SRC[>>87]]。
:[86] [CODE(URI)@en[[[error_uri]]]]:[[人間可読]]な[[誤り]]の説明を含む[[Webページ]]の [[URL]]
を指定して構いません [SRC[>>87]]。
]FIG]
;; [126] [[誤り符号]]によっては、他の [[HTTP]] [[状態符号]]を使うこともあるようです。
[127] [[Azure]] は [CODE(URI)@en[[[timestamp]]]]、[CODE(URI)@en[[[trace_id]]]]、
[CODE@en[[[correlation_id]]]]、[CODE@en[[[error_codes]]]] を追加しています [SRC[>>128]]。
[REFS[
- [128] [CITE@en[Token Issuance Endpoint Errors]] ([TIME[2015-03-05 10:47:08 +09:00]] 版) <https://msdn.microsoft.com/en-us/library/azure/dn645548.aspx>
- [156] [CITE[Understanding the Username-Password OAuth Authentication Flow]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_username_password_oauth_flow.htm>
- [157] [CITE[Understanding the OAuth Refresh Token Process]] ([TIME[2015-02-28 04:30:54 +09:00]] 版) <https://www.salesforce.com/us/developer/docs/api_rest/Content/intro_understanding_refresh_token_oauth.htm>
]REFS]
[51] [CODE(URI)@en[[[error]]]] が [CODE@en[[[invalid_client]]]] の場合には、
[CODE(HTTP)[[[401]]]] [[応答]]とすることもできます。
[[クライアント]]が [CODE(HTTP)@en[[[Authorization:]]]] [[ヘッダー]]で[[認証]]を試みた場合には、
[CODE(HTTP)[[[401]]]] [[応答]]と [CODE(HTTP)@en[[[WWW-Authenticate:]]]]
[[ヘッダー]] ([[auth-scheme]] は[[要求]]で指定されたもの) を使って[[応答]]しなければ[['''なりません''']] [SRC[>>87]]。