<commit_before># scala-oauth2-provider example with Slick

- [scala-oauth2-provider](https://github.com/nulab/scala-oauth2-provider) 0.17.x
- [Play Framework](https://www.playframework.com/) 2.5.x
- [Slick-OFM](http://slick.lightbend.com/) 3.1.1

Inspired from [tsuyoshizawa's](https://github.com/tsuyoshizawa) [implementation](https://github.com/tsuyoshizawa/scala-oauth2-provider-example-skinny-orm) of the oauth2 server using Skinny ORM. I instead wanted to use Slick Functional Relational Mapper to leverage the performance advantages that it provided.

## Running Play Framework with evolutions

```
$ activator run
```

## Try to create access tokens using curl

### Client credentials

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secret" -d "grant_type=client_credentials"
```

### Authorization code

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
```

NOTE: A service needs to generate `code` in advance. In this example, the code has been inserted in database by evolutions.

### Password

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
```

### Refresh token

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=${refresh_token}" -d "grant_type=refresh_token"
```

NOTE: `${refresh_token}` is you got `refresh_token` from json of password grant. (client_id and client_secret are also same with password grant)

### Access resource using access_token

You can access application resource using access token.

```
$ curl --dump-header - -H "Authorization: Bearer ${access_token}" http://localhost:9000/resources
```

In this example, server just returns authorized user information.

```
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 90

{"account":{"email":"<EMAIL>"},"clientId":"alice_client_id2","redirectUri":null}
```
### Various test scenarios and its results

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secret" -d "grant_type=client_credentials"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<PASSWORD>"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secret" -d "grant_type=client_credential"
{"error":"unsupported_grant_type","error_description":"client_credential is not supported"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secre" -d "grant_type=client_credentials"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_i" -d "client_secret=bob_client_secret" -d "grant_type=client_credentials"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<KEY>"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_cod"
{"error":"unsupported_grant_type","error_description":"authorization_cod is not supported"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_cod" -d "grant_type=authorization_code"
{"error":"invalid_grant","error_description":"Authorized information is not found by the code"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secre" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_i" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<KEY>"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=passwor"
{"error":"unsupported_grant_type","error_description":"passwor is not supported"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_grant","error_description":"username or password is incorrect"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_grant","error_description":"username or password is incorrect"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=${refresh_token}" -d "grant_type=refresh_toke"
{"error":"unsupported_grant_type","error_description":"refresh_toke is not supported"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=${refresh_token}" -d "grant_type=refresh_token"
{"error":"invalid_grant","error_description":"Authorized information is not found by the refresh token"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=gymRoFktrUSYOmVCE0EwoZKENLDCq4CaxaXQG03O" -d "grant_type=refresh_token"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<KEY>"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret" -d "refresh_token=<KEY>" -d "grant_type=refresh_token"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret2" -d "refresh_token=<KEY>" -d "grant_type=refresh_token"
{"error":"invalid_client","error_description":"Invalid client is detected"}
naveenkumar at Naveens-MacBook-Pro in ~
$ curl --dump-header - -H "Authorization: Bearer ${access_token}" http://localhost:9000/resources
HTTP/1.1 400 Bad Request
WWW-Authenticate: Bearer error="invalid_request", error_description="Access token is not found"
Content-Length: 0
Date: Wed, 11 Jan 2017 03:22:36 GMT

naveenkumar at Naveens-MacBook-Pro in ~
$ curl --dump-header - -H "Authorization: Bearer CCWd7AGHeEeV3YNOsBhKSK4OZw5DoudyWWQDRkvZ" http://localhost:9000/resources
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="The access token is not found"
Content-Length: 0
Date: Wed, 11 Jan 2017 03:23:12 GMT
```<commit_msg>Added the last test scenario<commit_after># scala-oauth2-provider example with Slick

- [scala-oauth2-provider](https://github.com/nulab/scala-oauth2-provider) 0.17.x
- [Play Framework](https://www.playframework.com/) 2.5.x
- [Slick-OFM](http://slick.lightbend.com/) 3.1.1

Inspired from [tsuyoshizawa's](https://github.com/tsuyoshizawa) [implementation](https://github.com/tsuyoshizawa/scala-oauth2-provider-example-skinny-orm) of the oauth2 server using Skinny ORM. I instead wanted to use Slick Functional Relational Mapper to leverage the performance advantages that it provided.

## Running Play Framework with evolutions

```
$ activator run
```

## Try to create access tokens using curl

### Client credentials

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secret" -d "grant_type=client_credentials"
```

### Authorization code

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
```

NOTE: A service needs to generate `code` in advance. In this example, the code has been inserted in database by evolutions.

### Password

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
```

### Refresh token

```
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=${refresh_token}" -d "grant_type=refresh_token"
```

NOTE: `${refresh_token}` is you got `refresh_token` from json of password grant. (client_id and client_secret are also same with password grant)

### Access resource using access_token

You can access application resource using access token.

```
$ curl --dump-header - -H "Authorization: Bearer ${access_token}" http://localhost:9000/resources
```

In this example, server just returns authorized user information.

```
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 90

{"account":{"email":"<EMAIL>"},"clientId":"alice_client_id2","redirectUri":null}
```
### Various test scenarios and its results

```
naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secret" -d "grant_type=client_credentials"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<PASSWORD>"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secret" -d "grant_type=client_credential"
{"error":"unsupported_grant_type","error_description":"client_credential is not supported"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_id" -d "client_secret=bob_client_secre" -d "grant_type=client_credentials"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=bob_client_i" -d "client_secret=bob_client_secret" -d "grant_type=client_credentials"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<KEY>"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_cod"
{"error":"unsupported_grant_type","error_description":"authorization_cod is not supported"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_cod" -d "grant_type=authorization_code"
{"error":"invalid_grant","error_description":"Authorized information is not found by the code"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secre" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_i" -d "client_secret=alice_client_secret" -d "redirect_uri=http://localhost:3000/callback" -d "code=bob_code" -d "grant_type=authorization_code"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"token_type":"Bearer","access_token":"CCWd7AGHeEeV3YNOsBhKSK4OZw5DoudyWWQDRkvZ","expires_in":3599,"refresh_token":"gym<PASSWORD>USYOmV<PASSWORD>"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=passwor"
{"error":"unsupported_grant_type","error_description":"passwor is not supported"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_grant","error_description":"username or password is incorrect"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_grant","error_description":"username or password is incorrect"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret2" -d "username=<EMAIL>" -d "password=<PASSWORD>" -d "grant_type=password"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=${refresh_token}" -d "grant_type=refresh_toke"
{"error":"unsupported_grant_type","error_description":"refresh_toke is not supported"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=${refresh_token}" -d "grant_type=refresh_token"
{"error":"invalid_grant","error_description":"Authorized information is not found by the refresh token"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret2" -d "refresh_token=<KEY>" -d "grant_type=refresh_token"
{"token_type":"Bearer","access_token":"<KEY>","expires_in":3599,"refresh_token":"<KEY>"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id2" -d "client_secret=alice_client_secret" -d "refresh_token=<KEY>" -d "grant_type=refresh_token"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl http://localhost:9000/oauth/access_token -X POST -d "client_id=alice_client_id" -d "client_secret=alice_client_secret2" -d "refresh_token=<KEY>" -d "grant_type=refresh_token"
{"error":"invalid_client","error_description":"Invalid client is detected"}

naveenkumar at Naveens-MacBook-Pro in ~
$ curl --dump-header - -H "Authorization: Bearer ${access_token}" http://localhost:9000/resources
HTTP/1.1 400 Bad Request
WWW-Authenticate: Bearer error="invalid_request", error_description="Access token is not found"
Content-Length: 0
Date: Wed, 11 Jan 2017 03:22:36 GMT

naveenkumar at Naveens-MacBook-Pro in ~
$ curl --dump-header - -H "Authorization: Bearer CCWd7AGHeEeV3YNOsBhKSK4OZw5DoudyWWQDRkvZ" http://localhost:9000/resources
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer error="invalid_token", error_description="The access token is not found"
Content-Length: 0
Date: Wed, 11 Jan 2017 03:23:12 GMT

naveenkumar at Naveens-MacBook-Pro in ~
$ curl --dump-header - -H "Authorization: Bearer <KEY>" http://localhost:9000/resources
HTTP/1.1 200 OK
Content-Length: 90
Content-Type: application/json
Date: Wed, 11 Jan 2017 03:44:34 GMT

{"account":{"email":"<EMAIL>"},"clientId":"alice_client_id2","redirectUri":null}
```
{'fraction_non_alphanumeric': 0.1431329576288875, 'fraction_numerical': 0.02588186182425381, 'mean_word_length': 7.107021996615905, 'pattern_counts': {'":': 108, '<': 56, '<?xml version=': 0, '>': 56, 'https://': 8, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1479946', 'n_tokens_mistral': 7126, 'n_tokens_neox': 6614, 'n_words': 1370}