Commit 00709f0

mo <mo@mokhan.ca>
2018-10-28 21:13:25
document the password grant
1 parent 8d68697
doc/_includes/get-well-known-oauth-authorization-server.html
@@ -34,7 +34,7 @@ Referrer-Policy: strict-origin-when-cross-origin
 Content-Type: application/json; charset=utf-8
 Etag: W/"7f1eee6ebfc3008c58d630548ed1707c"
 Cache-Control: max-age=0, private, must-revalidate
-X-Request-Id: fd71ef5e-db78-40c8-9370-5bf7f895d8ce
+X-Request-Id: a8ead785-8586-4d59-8bbe-8ec7c38445bf
 Transfer-Encoding: chunked
 ```
 
doc/_includes/oauth-tokens-authorization-code.html
@@ -6,11 +6,11 @@ Example curl request:
 ```bash
 $ curl http://localhost:5000/oauth/tokens \
   -X POST \
-  -d '{"grant_type":"authorization_code","code":"FbMvnDUuS9P197L1VAa8wTaV"}' \
+  -d '{"grant_type":"authorization_code","code":"53RFPrXJkRGCcC5yqKfJrhGx"}' \
   -H "Accept: application/json" \
   -H "Content-Type: application/json" \
   -H "User-Agent: net/hippie 0.1.9" \
-  -H "Authorization: Basic YjBkYzc4MzUtOGI1NC00NjRhLTk0MmItN2E5NDBhZmM2ZDllOjFhWWNBVWZ0R0s1Q0xBbk1HODdYTmZWdg==" \
+  -H "Authorization: Basic NzQwY2FjNmYtNWMxZC00YTBmLTkyYmEtNTFhMGI0OGVjYjgxOldZY3VEOW9laGY5dWRMdDhubXIzSGdRag==" \
   -H "Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
 ```
 Request Headers:
@@ -19,7 +19,7 @@ Request Headers:
 Accept: application/json
 Content-Type: application/json
 User-Agent: net/hippie 0.1.9
-Authorization: Basic YjBkYzc4MzUtOGI1NC00NjRhLTk0MmItN2E5NDBhZmM2ZDllOjFhWWNBVWZ0R0s1Q0xBbk1HODdYTmZWdg==
+Authorization: Basic NzQwY2FjNmYtNWMxZC00YTBmLTkyYmEtNTFhMGI0OGVjYjgxOldZY3VEOW9laGY5dWRMdDhubXIzSGdRag==
 Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
 ```
 
@@ -28,7 +28,7 @@ Request Body:
 ```json
 {
   "grant_type": "authorization_code",
-  "code": "FbMvnDUuS9P197L1VAa8wTaV"
+  "code": "53RFPrXJkRGCcC5yqKfJrhGx"
 }
 ```
 
@@ -44,8 +44,8 @@ Referrer-Policy: strict-origin-when-cross-origin
 Cache-Control: private, no-store
 Pragma: no-cache
 Content-Type: application/json; charset=utf-8
-Etag: W/"2778e3b5f668fcdcd35b51a2ef5cf5c8"
-X-Request-Id: c21b24f2-8ffe-4759-bced-d888c7acd509
+Etag: W/"e285a69c08c19a459453f718028a5f5e"
+X-Request-Id: 86e14b3b-0897-4657-8669-b311ac950caa
 Transfer-Encoding: chunked
 ```
 
@@ -53,10 +53,10 @@ Transfer-Encoding: chunked
 Response Body:
 ```json
 {
-  "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NDA3NjQyMjAsImlhdCI6MTU0MDc2MDYyMCwiaXNzIjoiaHR0cDovL3Byb29mLnRlc3QvbWV0YWRhdGEiLCJuYmYiOjE1NDA3NjA2MjAsImF1ZCI6ImIwZGM3ODM1LThiNTQtNDY0YS05NDJiLTdhOTQwYWZjNmQ5ZSIsImp0aSI6ImU3ODYyNjNkLTkzYmItNDFjMy05ODk2LTQxMTg0NWNhZDQxZSIsInN1YiI6IjM3NzI4NGRiLWExMGYtNGViMC04YTA5LWRhNjdiMThlNGIzNiIsInRva2VuX3R5cGUiOiJhY2Nlc3MifQ.pL7TpT2AeUPTNodAhUn8T8GJOONEbKp10sWoN8D6JT_2fEJcnEKmm-AyJ0GbbFP08ZeIHJxb7hBVsPFI7clXxVq7tYy51H0cDF9SBrDnOiBsXb3Ku2iCfs0R2-7OkeYY-uay1-S98vZwYs3OzqCxC1rB5LUumLVhpe9lo0qD9DXb6pKYjHW7CqRbPNe4vEEEeRxI-u7_zxx6yYn-Sk6tfu8sf-urr-iX6An7grc8aZJ52xrPNCEjiMzPgGu6SF6LXu-C-d_l56hpc982Rol9bMyDXFRpiJ8SnuZiu5cMQ1WDGshURjfvPRGNT4Rn-wbTOERqa484Rwmn8X4n0yIFcQ",
+  "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NDA3NjQ3MzEsImlhdCI6MTU0MDc2MTEzMSwiaXNzIjoiaHR0cDovL3Byb29mLnRlc3QvbWV0YWRhdGEiLCJuYmYiOjE1NDA3NjExMzEsImF1ZCI6Ijc0MGNhYzZmLTVjMWQtNGEwZi05MmJhLTUxYTBiNDhlY2I4MSIsImp0aSI6IjZkZTRkODA0LTdmODItNDlmYy1hYTAxLTA1OTIxMzRmMDQ0NiIsInN1YiI6ImZiMTZkMDUwLWRjZWUtNDcxNS05MjViLWRjMTY5YmE0OGY5YiIsInRva2VuX3R5cGUiOiJhY2Nlc3MifQ.dqjf455ehqQ3n_FskTlngYlRmVQZ8UdNbpoybnwVzYc6JSwI_8kFrS2zCNxexn0jqpMmzoTyuVvzqkR1-6FUZmbdFBnR5edEaGeG06FmrWqCQczHb8k4pIT_dK3IjaZdgbmW_YwprmIb5CUAp__dRw1c8AgO-AI-ScG5B6vG7_RnTXxVMk0yMrsD8V7cZQEXRZKH-4WW5TtPDNDaq3t2baHfM6cTgCFP-J0_7lTOYXgyQucPfmHa3-u7rHHRMgt8QdgV9qf_7xpXjJEIyE1KKxPj-RGWjlOqAtwwrpsN8ZhApIXi1ItriJxApq7or_OWzLoA1AhtmYBLljnH3_gHPA",
   "token_type": "Bearer",
   "expires_in": 3600,
-  "refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NDA4NDcwMjAsImlhdCI6MTU0MDc2MDYyMCwiaXNzIjoiaHR0cDovL3Byb29mLnRlc3QvbWV0YWRhdGEiLCJuYmYiOjE1NDA3NjA2MjAsImF1ZCI6ImIwZGM3ODM1LThiNTQtNDY0YS05NDJiLTdhOTQwYWZjNmQ5ZSIsImp0aSI6ImUxODNiMzExLWMyZjktNGQ3Mi1hOGU2LTdlMjU0YzlkMjE2ZiIsInN1YiI6IjM3NzI4NGRiLWExMGYtNGViMC04YTA5LWRhNjdiMThlNGIzNiIsInRva2VuX3R5cGUiOiJyZWZyZXNoIn0.m0Ht55DA-14kJOje9NqW35Kcp3IW_CuXyvzsqescKm4ss5TI_pg3ku8cuUpgszTSiAVf1RW-ETkodrazRlje2yi34Fjn6v5FbXqtIk8nl_8rW_M-aVLZMgd4PGQ5MUGp1blua6uI9o6XKHxOCLbucSpYZ7XtvKVav2OuYeU0_j7IeC_SEQj0tAv6LiMgZ1z3IG4ZysvWHDVPOEMX7Z-klJVXU4cND4MwA925ogSjt6jRaCWpgrigEWrtO3Li6dapQ-EPeJa2GRE6G9QHSIc41wDcRCty5m7Bbd044KRAkvJRhCGrkSMTE7xLPW8xQriBGVKZElmRvySBixofbXFlfg"
+  "refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NDA4NDc1MzEsImlhdCI6MTU0MDc2MTEzMSwiaXNzIjoiaHR0cDovL3Byb29mLnRlc3QvbWV0YWRhdGEiLCJuYmYiOjE1NDA3NjExMzEsImF1ZCI6Ijc0MGNhYzZmLTVjMWQtNGEwZi05MmJhLTUxYTBiNDhlY2I4MSIsImp0aSI6Ijk3YjlkZWJkLTM3YjAtNDYyOC05NWU4LTdjMWZkMDI2OTBmMCIsInN1YiI6ImZiMTZkMDUwLWRjZWUtNDcxNS05MjViLWRjMTY5YmE0OGY5YiIsInRva2VuX3R5cGUiOiJyZWZyZXNoIn0.NSlgUB6dSWrbLsHtf6SEACw3MqfhBzjK-5kZRgNt8K0STBrNd_3ecT1sZmqyVwfsC_qD1h2Aw2fwU8ESnb4Gr69zzI8ahezDHg2CjYPvrToYVABv8hul_z0-qIPEC8mTh2NJQfheeAvebqq7GufeDZSjGds_sLWrDxfzCrcgdq2cTapan5lzXyjnYzYyUa6uB4Ppw2wpp9oVXEzdHMWT9MKRh88oiZnSY_L_vzbA2ZlxFkZCaEYpDTeTGVAvfC7n3iEYmHJMj0I8sLIjV5HXfZhiEtnO7-4ZZtdPMBqPHjM4oGqsOpVKETvEF4J8dlYUNQ3UcJtcO7LxBXvp2D7jdQ"
 }
 ```
 
doc/_includes/oauth-tokens-password.html
@@ -0,0 +1,64 @@
+
+#### POST http://localhost:5000/oauth/tokens
+
+Example curl request:
+
+```bash
+$ curl http://localhost:5000/oauth/tokens \
+  -X POST \
+  -d '{"grant_type":"password","username":"allen@volkmanweissnat.info","password":"s1b5RDJmQY8G"}' \
+  -H "Accept: application/json" \
+  -H "Content-Type: application/json" \
+  -H "User-Agent: net/hippie 0.1.9" \
+  -H "Authorization: Basic YjhkOTgzNTMtMGVjMC00ZTlhLTg0MDItNWE2OWUxZjY5NzZkOkJYd0RybjlWcWFRamRHSjM1OGhuUFNSSg==" \
+  -H "Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3"
+```
+Request Headers:
+
+```text
+Accept: application/json
+Content-Type: application/json
+User-Agent: net/hippie 0.1.9
+Authorization: Basic YjhkOTgzNTMtMGVjMC00ZTlhLTg0MDItNWE2OWUxZjY5NzZkOkJYd0RybjlWcWFRamRHSjM1OGhuUFNSSg==
+Accept-Encoding: gzip;q=1.0,deflate;q=0.6,identity;q=0.3
+```
+
+
+Request Body:
+```json
+{
+  "grant_type": "password",
+  "username": "allen@volkmanweissnat.info",
+  "password": "s1b5RDJmQY8G"
+}
+```
+
+Response Headers:
+
+```text
+X-Frame-Options: SAMEORIGIN
+X-Xss-Protection: 1; mode=block
+X-Content-Type-Options: nosniff
+X-Download-Options: noopen
+X-Permitted-Cross-Domain-Policies: none
+Referrer-Policy: strict-origin-when-cross-origin
+Cache-Control: private, no-store
+Pragma: no-cache
+Content-Type: application/json; charset=utf-8
+Etag: W/"b22c1725b3a24d9a88d0d82adb5ccead"
+X-Request-Id: 5200b121-3660-429b-be52-a2e9b732b2f4
+Transfer-Encoding: chunked
+```
+
+
+Response Body:
+```json
+{
+  "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NDA3NjQ3MzEsImlhdCI6MTU0MDc2MTEzMSwiaXNzIjoiaHR0cDovL3Byb29mLnRlc3QvbWV0YWRhdGEiLCJuYmYiOjE1NDA3NjExMzEsImF1ZCI6ImI4ZDk4MzUzLTBlYzAtNGU5YS04NDAyLTVhNjllMWY2OTc2ZCIsImp0aSI6IjRjYjc0ZjI4LTEwYmEtNDEwYi04NGU5LTg4Mzc2MzQ3NWZjMSIsInN1YiI6IjNiOTRlZGIwLTJlYWItNDAyYi1hZTg2LThmMjVlMmQzMjQ0OSIsInRva2VuX3R5cGUiOiJhY2Nlc3MifQ.PVN9lWyxjibLlQqGQIS-7RIb64YbUanm-kI8GFibEgw4WmrOGNcuk5Te-w6ISNt0RlluIC1lgOOdBBr6vRVZZoUC8T72l26QzbEHjKANq_2aZffyojiGSoiU9KCXHFjTX4RQCFV40vxje8olCs5x3CpkBszfH24eAhFgvSp8IcDg62fwV98gCWb3fAK3evRmN5A5N66zxpLuESuVX8rG0WjCowdEuhC9f3jxLyKpBX2keFpO5Fq2Ina8HlkQhi4UchMwm2eKtEV63T8UVFojDlsDc-J7KNc5yVRR2XeYmaoDrEJ4oPf5OshbOS58yJ6XpENM4onfRW5O2Nof31SU1w",
+  "token_type": "Bearer",
+  "expires_in": 3600,
+  "refresh_token": "eyJhbGciOiJSUzI1NiJ9.eyJleHAiOjE1NDA4NDc1MzEsImlhdCI6MTU0MDc2MTEzMSwiaXNzIjoiaHR0cDovL3Byb29mLnRlc3QvbWV0YWRhdGEiLCJuYmYiOjE1NDA3NjExMzEsImF1ZCI6ImI4ZDk4MzUzLTBlYzAtNGU5YS04NDAyLTVhNjllMWY2OTc2ZCIsImp0aSI6IjQ5NDFhMTgyLWNlZDgtNDlhNi1hZTY3LTdlMzQ3YmU3MDgyZCIsInN1YiI6IjNiOTRlZGIwLTJlYWItNDAyYi1hZTg2LThmMjVlMmQzMjQ0OSIsInRva2VuX3R5cGUiOiJyZWZyZXNoIn0.DSvKplo6e_05xQTaYQkmKHDQuOwrFeM45UG5QAH5WxbMtG5MD715PCt7TzySy49A5cOx-n8JC11sMvRmkkB2UncwGmaNyi_4AWVnLeucYIm1ApED71AlNbn8hMr8uWfnFRXUJfA4acbNr0nI1bRC5tChKohkurV2BvMNq60rsMV4NEgjaXja3t5rqURtPAskirMWtYLNGSnVkkYQp_ou6YcRDHn2AtIBygccJDZBQMsCHuU7la32wZmsKeJisujatAu0gI8SZXSAWjX00EVwCMIJ6_yQkTNNvgSQCmvkT4DOPavFM-dgwnbYO1dst1MbxCuVCGDIZTGdehb8YwvjMw"
+}
+```
+
+
doc/_posts/2018-10-28-oauth-tokens.markdown
@@ -8,7 +8,7 @@ categories: oauth
 
 The Tokens endpoint adheres to [RFC-6749](https://tools.ietf.org/html/rfc6749).
 
-## Authorization Code Grant Flow
+## Authorization Code Grant
 
 ```text
     +----------+
@@ -40,3 +40,28 @@ The Tokens endpoint adheres to [RFC-6749](https://tools.ietf.org/html/rfc6749).
 [RFC-6749 Section 4.1](https://tools.ietf.org/html/rfc6749#section-4.1)
 
 {% include oauth-tokens-authorization-code.html %}
+
+## Resource Owner Password Credentials Grant
+
+```text
+    +----------+
+    | Resource |
+    |  Owner   |
+    |          |
+    +----------+
+        v
+        |    Resource Owner
+       (A) Password Credentials
+        |
+        v
+    +---------+                                  +---------------+
+    |         |>--(B)---- Resource Owner ------->|               |
+    |         |         Password Credentials     | Authorization |
+    | Client  |                                  |     Server    |
+    |         |<--(C)---- Access Token ---------<|               |
+    |         |    (w/ Optional Refresh Token)   |               |
+    +---------+                                  +---------------+
+```
+[Section 4.3](https://tools.ietf.org/html/rfc6749#section-4.3)
+
+{% include oauth-tokens-password.html %}
spec/documentation.rb
@@ -31,6 +31,8 @@ RSpec.describe "documentation" do
   let(:hippie) { Net::Hippie::Client.new(verify_mode: OpenSSL::SSL::VERIFY_NONE) }
   let(:host) { ENV.fetch('HOST', 'proof.test') }
   let(:scheme) { ENV.fetch('SCHEME', 'https') }
+  let(:client) { create(:client) }
+  let(:user) { create(:user) }
 
   specify do
     VCR.use_cassette("get-well-known-oauth-authorization-server") do
@@ -40,7 +42,6 @@ RSpec.describe "documentation" do
   end
 
   specify do
-    client = create(:client)
     authorization = create(:authorization, client: client)
     headers = { 'Authorization' => ActionController::HttpAuthentication::Basic.encode_credentials(client.to_param, client.password) }
     body = { grant_type: 'authorization_code', code: authorization.code }
@@ -49,4 +50,13 @@ RSpec.describe "documentation" do
       expect(response.code).to eql('200')
     end
   end
+
+  specify do
+    headers = { 'Authorization' => ActionController::HttpAuthentication::Basic.encode_credentials(client.to_param, client.password) }
+    body = { grant_type: 'password', username: user.email, password: user.password }
+    VCR.use_cassette("oauth-tokens-password") do
+      response = hippie.post("#{scheme}://#{host}/oauth/tokens", body: body, headers: headers)
+      expect(response.code).to eql('200')
+    end
+  end
 end