Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 11 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# WatcherEx ![Build](https://github.com/lcpojr/watcher_ex/workflows/CI/badge.svg) [![Coverage](https://coveralls.io/repos/github/lcpojr/watcher_ex/badge.svg)](https://coveralls.io/github/lcpojr/watcher_ex)

**This is a work in progress and every contribution is welcome :)**

**TODO: Add description**

## Requirements
Expand All @@ -26,85 +28,24 @@ In order to prepare the application run:

Now that you have everything configured you can just call `mix phx.server` to get all applications running. The service will be available at `localhost:4000`.

### Making requests
### Seeding the database

You can run the seeds in order to create an user and application for tests by using `mix seed`.
In order to gen you user and application data run on project iex (`iex -S mix phx.server`);
To get the user and application data check out the database on `localhost:8181` or run the project with using (`iex -S mix phx.server`) and execute the commands bellow.

```elixir
# Getting all user identities
# The user password will be `admin`
ResourceManager.Repo.all(ResourceManager.Identity.Schemas.User) |> ResourceManager.Repo.preload([:scopes])
ResourceManager.Repo.all(ResourceManager.Identity.Schemas.ClientApplication) |> ResourceManager.Repo.preload([:scopes])
```

**Sign in by Resource Owner Flow**

Request:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/token \
-H "Content-Type: application/json" \
-d '{"username":"admin", "password":"admin", "grant_type":"password", "scope":"admin:read admin:write", "client_id": "2e455bb1-0604-4812-9756-36f7ab23b8d9", "client_secret": "$2b$12$BSrTLJnb0Vfuk1iiSzw3MehAvgztbMYpnhneVLQhkoZbxAXBGUCFe"}'
```

Response (200):

```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDc5NzU2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJuYmYiOjE2MDA3OTAzNjcsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.LWniDC38j2kW8ER8kgDnVVJO0eOXWGNq0KqXooMl-5s",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjM2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210OG5vbjRkZHQ5YzgwMDAxcTEiLCJuYmYiOjE2MDA3OTAzNjcsInR5cCI6IkJlYXJlciJ9.U010q6KUB04K8rIU9rVnW_AOI1q5XSXSGIYdL1moaOA",
"expires_in": 7200000,
"token_type": "Bearer"
}
```

**Sign in by Refresh Token Flow**

Request:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/token \
-H "Content-Type: application/json" \
-d '{"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjM2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210OG5vbjRkZHQ5YzgwMDAxcTEiLCJuYmYiOjE2MDA3OTAzNjcsInR5cCI6IkJlYXJlciJ9.U010q6KUB04K8rIU9rVnW_AOI1q5XSXSGIYdL1moaOA", "grant_type": "refresh_token"}'
```

Response (200):

```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDc5NzgwOSwiaWF0IjoxNjAwNzkwNjA5LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpZDUwYXRja3JiMzMyZWswMDAxczEiLCJuYmYiOjE2MDA3OTA2MDksInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.GnuyK5JTgg0PCeUtT79s847a3qPWgBjE8UqYoK1DG8o",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpZDUwYXRja3JiMzMyZWswMDAxczEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjYwOSwiaWF0IjoxNjAwNzkwNjA5LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpZDUwYXRpOHJ2MzMyZWswMDAxdDEiLCJuYmYiOjE2MDA3OTA2MDksInR5cCI6IkJlYXJlciJ9.HIL0AMMKJdYUibSXyYXfYGBEMIZsuudvFUHcF-VjXRg",
"expires_in": 7200000,
"token_type": "Bearer"
}
```

**Sign out all active sessions**

Request:

```sh
curl -X POST api/v1/auth/protocol/openid-connect/logout-all-sessions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDgyMzMxNiwiaWF0IjoxNjAwODE2MTE2LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JqcmhuMHNxdDlncjk3ZXMwMDAzMDMiLCJuYmYiOjE2MDA4MTYxMTYsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.NxFH6MIOFGc54UR9EVLPFB0m-6b-YMyXhZrOuGxErdw"
```

Response (204)

`No content`

**Sign out the given session**

Request:

```sh
curl -X POST api/v1/auth/protocol/openid-connect/logout \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDgyMzMxNiwiaWF0IjoxNjAwODE2MTE2LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JqcmhuMHNxdDlncjk3ZXMwMDAzMDMiLCJuYmYiOjE2MDA4MTYxMTYsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.NxFH6MIOFGc54UR9EVLPFB0m-6b-YMyXhZrOuGxErdw"
# Getting all client application identities
# Check out for the client secret
ResourceManager.Repo.all(ResourceManager.Identity.Schemas.ClientApplication) |> ResourceManager.Repo.preload([:scopes])
```

Response (204)
### Making requests

`No content`
Check out the rest api guide on the specific application `README.md`.

## Testing

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ defmodule Authenticator.SignIn.Commands.ClientCredentials do
"azp" => application.name,
"sub" => application.id,
"typ" => "Bearer",
"identity" => "user",
"identity" => "application",
"scope" => build_scope(application, scope)
})
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule Authenticator.SignOut.Commands.SignOutAllSessions do
|> Repo.transaction()
|> case do
{:ok, %{invalidate: 0}} ->
Logger.info("Succeeds on command but any active session was found")
Logger.info("Succeeds on command but none session was found")
{:error, :not_active}

{:ok, %{invalidate: count}} ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ defmodule Authenticator.SignIn.Commands.ClientCredentialsTest do
"jti" => jti,
"nbf" => _,
"scope" => ^scope,
"identity" => "user",
"identity" => "application",
"sub" => ^subject_id,
"typ" => ^typ
}} = AccessToken.verify_and_validate(access_token)
Expand Down
15 changes: 13 additions & 2 deletions apps/resource_manager/lib/identity/schemas/client_application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ defmodule ResourceManager.Identity.Schemas.ClientApplication do
|> validate_length(:name, min: 1, max: 150)
|> validate_inclusion(:status, @possible_statuses)
|> validate_inclusion(:protocol, @possible_protocols)
|> validate_inclusion(:grant_flows, @possible_grant_flows)
|> validate_inclusion(:access_type, @possible_access_types)
|> unique_constraint(:name)
|> validate_grant_flows()
|> generate_secret()
end

Expand All @@ -83,11 +83,22 @@ defmodule ResourceManager.Identity.Schemas.ClientApplication do
|> validate_length(:name, min: 1, max: 150)
|> validate_inclusion(:status, @possible_statuses)
|> validate_inclusion(:protocol, @possible_protocols)
|> validate_inclusion(:grant_flows, @possible_grant_flows)
|> validate_inclusion(:access_type, @possible_access_types)
|> unique_constraint(:name)
|> validate_grant_flows()
end

defp validate_grant_flows(%{valid?: true, changes: %{grant_flows: flows}} = changeset) do
if Enum.all?(flows, &(&1 in @possible_grant_flows)) do
changeset
else
opts = [validation: :subset, enum: @possible_grant_flows]
add_error(changeset, :grant_flows, "is invalid", opts)
end
end
Comment on lines +91 to +98
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is just to give a customized response?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah !
It's better to add the error as a changeset validation failure because that's the expected response.
This helps out a lot when we have a default controller fallback that know how to handle changeset errors.


defp validate_grant_flows(changeset), do: changeset

@doc false
def possible_statuses, do: @possible_statuses

Expand Down
2 changes: 1 addition & 1 deletion apps/resource_manager/priv/repo/seeds.exs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Repo.transaction(fn ->
name: "admin",
description: "Admin test application",
status: "active",
grant_flows: ["resource_owner", "refresh_token"],
grant_flows: ["resource_owner", "refresh_token", "client_credentials"],
secret: Bcrypt.hash_pwd_salt("my-secret")
})

Expand Down
98 changes: 97 additions & 1 deletion apps/rest_api/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,99 @@
# RestAPI

**TODO: Add description**
This application handles all requests on the restfull api.
It exposes public and admin endpoints.

## Testing it locally

Follow the `Running it locally` guide on project `README.md` in order to know how to install all dependencies and get the server ready.

### Sign in by Resource Owner Flow

**Request**:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/token \
-H "Content-Type: application/json" \
-d '{"username":"admin", "password":"admin", "grant_type":"password", "scope":"admin:read admin:write", "client_id": "2e455bb1-0604-4812-9756-36f7ab23b8d9", "client_secret": "$2b$12$BSrTLJnb0Vfuk1iiSzw3MehAvgztbMYpnhneVLQhkoZbxAXBGUCFe"}'
```

**Response (200)**:

```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDc5NzU2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJuYmYiOjE2MDA3OTAzNjcsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.LWniDC38j2kW8ER8kgDnVVJO0eOXWGNq0KqXooMl-5s",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjM2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210OG5vbjRkZHQ5YzgwMDAxcTEiLCJuYmYiOjE2MDA3OTAzNjcsInR5cCI6IkJlYXJlciJ9.U010q6KUB04K8rIU9rVnW_AOI1q5XSXSGIYdL1moaOA",
"expires_in": 7200000,
"token_type": "Bearer"
}
```

### Sign in by Refresh Token Flow

**Request**:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/token \
-H "Content-Type: application/json" \
-d '{"refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjM2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210OG5vbjRkZHQ5YzgwMDAxcTEiLCJuYmYiOjE2MDA3OTAzNjcsInR5cCI6IkJlYXJlciJ9.U010q6KUB04K8rIU9rVnW_AOI1q5XSXSGIYdL1moaOA", "grant_type": "refresh_token"}'
```

**Response (200)**:

```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDc5NzgwOSwiaWF0IjoxNjAwNzkwNjA5LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpZDUwYXRja3JiMzMyZWswMDAxczEiLCJuYmYiOjE2MDA3OTA2MDksInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.GnuyK5JTgg0PCeUtT79s847a3qPWgBjE8UqYoK1DG8o",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpZDUwYXRja3JiMzMyZWswMDAxczEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjYwOSwiaWF0IjoxNjAwNzkwNjA5LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpZDUwYXRpOHJ2MzMyZWswMDAxdDEiLCJuYmYiOjE2MDA3OTA2MDksInR5cCI6IkJlYXJlciJ9.HIL0AMMKJdYUibSXyYXfYGBEMIZsuudvFUHcF-VjXRg",
"expires_in": 7200000,
"token_type": "Bearer"
}
```

### Sign in by Client Credentials Flow

**Request**:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/token \
-H "Content-Type: application/json" \
-d '{"grant_type":"client_credentials", "scope":"admin:read admin:write", "client_id": "2e455bb1-0604-4812-9756-36f7ab23b8d9", "client_secret": "$2b$12$BSrTLJnb0Vfuk1iiSzw3MehAvgztbMYpnhneVLQhkoZbxAXBGUCFe"}'
```

**Response (200)**:

```json
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDc5NzU2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJuYmYiOjE2MDA3OTAzNjcsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.LWniDC38j2kW8ER8kgDnVVJO0eOXWGNq0KqXooMl-5s",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdGkiOiIyb3JpY210ODQ3NTg1ZHQ5YzgwMDAxcDEiLCJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMzM4MjM2NywiaWF0IjoxNjAwNzkwMzY3LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JpY210OG5vbjRkZHQ5YzgwMDAxcTEiLCJuYmYiOjE2MDA3OTAzNjcsInR5cCI6IkJlYXJlciJ9.U010q6KUB04K8rIU9rVnW_AOI1q5XSXSGIYdL1moaOA",
"expires_in": 7200000,
"token_type": "Bearer"
}
```

### Sign out all active sessions

**Request**:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/logout-all-sessions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMTE1NzEyNCwiaWF0IjoxNjAxMTQ5OTI0LCJpZGVudGl0eSI6InVzZXIiLCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3M2cW5zN2ZxYjFvOGhrZDQwMDAxNTQiLCJuYmYiOjE2MDExNDk5MjQsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjIyZTk2MTA4LThkZDYtNGZiZS1iMjExLTY4OTM0YmJhNWJkNyIsInR0bCI6NzIwMCwidHlwIjoiQmVhcmVyIn0.EuIJtx_AGLrL2O7E7cBfsvEQymalO_A5-J0BX4PODwk"
```

**Response (204)**:

`No content`

### Sign out the given session

**Request**:

```sh
curl -X POST http://localhost:4000/api/v1/auth/protocol/openid-connect/logout \
-H "Content-Type: application/json" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiIyZTQ1NWJiMS0wNjA0LTQ4MTItOTc1Ni0zNmY3YWIyM2I4ZDkiLCJhenAiOiJhZG1pbiIsImV4cCI6MTYwMDgyMzMxNiwiaWF0IjoxNjAwODE2MTE2LCJpc3MiOiJXYXRjaGVyRXgiLCJqdGkiOiIyb3JqcmhuMHNxdDlncjk3ZXMwMDAzMDMiLCJuYmYiOjE2MDA4MTYxMTYsInNjb3BlIjoiYWRtaW46cmVhZCBhZG1pbjp3cml0ZSIsInN1YiI6IjdmNWViOWRjLWI1NTAtNDU4Ni05MWRjLTNjNzAxZWIzYjliYyIsInR5cCI6IkJlYXJlciJ9.NxFH6MIOFGc54UR9EVLPFB0m-6b-YMyXhZrOuGxErdw"
```

**Response (204)**:

`No content`
54 changes: 24 additions & 30 deletions apps/rest_api/lib/controllers/public/auth.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,59 +14,53 @@ defmodule RestAPI.Controllers.Public.Auth do
The accepted flow are:
- Resource Owner (Authenticates using username and password);
- Refresh Token (Authenticates using an refresh token);
- Client Credentials (Authenticates using client_id and secret);
"""
@spec sign_in(conn :: Plug.Conn.t(), params :: map()) :: Plug.Conn.t()
def sign_in(conn, %{"grant_type" => "password"} = params) do
params
|> Commands.sign_in_resource_owner()
|> case do
{:ok, response} ->
conn
|> put_status(:ok)
|> put_view(SignIn)
|> render("sign_in.json", response: response)

{:error, _reason} = error ->
error
end
|> parse_sign_in_response(conn)
end

def sign_in(conn, %{"grant_type" => "refresh_token"} = params) do
params
|> Commands.sign_in_refresh_token()
|> case do
{:ok, response} ->
conn
|> put_status(:ok)
|> put_view(SignIn)
|> render("sign_in.json", response: response)
|> parse_sign_in_response(conn)
end

{:error, _reason} = error ->
error
end
def sign_in(conn, %{"grant_type" => "client_credentials"} = params) do
params
|> Commands.sign_in_client_credentials()
|> parse_sign_in_response(conn)
end

defp parse_sign_in_response({:error, _any} = error, _conn), do: error

defp parse_sign_in_response({:ok, response}, conn) do
conn
|> put_status(:ok)
|> put_view(SignIn)
|> render("sign_in.json", response: response)
end

@doc "Logout the authenticated subject session."
@spec sign_out(conn :: Plug.Conn.t(), params :: map()) :: Plug.Conn.t()
def sign_out(%{private: %{session: session}} = conn, _params) do
session.jti
session
|> Commands.sign_out_session()
|> case do
{:ok, _count} -> send_resp(conn, :no_content, "")
{:error, :not_active} -> send_resp(conn, :forbidden, "")
{:error, :not_found} -> send_resp(conn, :not_found, "")
end
|> parse_sign_out_response(conn)
end

@doc "Logout subject authenticated sessions."
@spec sign_out_all_sessions(conn :: Plug.Conn.t(), params :: map()) :: Plug.Conn.t()
def sign_out_all_sessions(%{private: %{session: session}} = conn, _params) do
session.subject_id
|> Commands.sign_out_all_sessions(session.subject_type)
|> case do
{:ok, _count} -> send_resp(conn, :no_content, "")
{:error, :not_active} -> send_resp(conn, :forbidden, "")
{:error, :not_found} -> send_resp(conn, :not_found, "")
end
|> parse_sign_out_response(conn)
end

defp parse_sign_out_response({:ok, _any}, conn), do: send_resp(conn, :no_content, "")
defp parse_sign_out_response({:error, :not_active}, conn), do: send_resp(conn, :forbidden, "")
defp parse_sign_out_response({:error, :not_found}, conn), do: send_resp(conn, :not_found, "")
end
6 changes: 1 addition & 5 deletions apps/rest_api/lib/plugs/authentication.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ defmodule RestAPI.Plugs.Authentication do
with {:header, [access_token | _]} <- {:header, get_req_header(conn, "authorization")},
{:bearer, "Bearer " <> access_token} <- {:bearer, access_token},
{:token, {:ok, claims}} <- {:token, Authenticator.validate_access_token(access_token)},
{:session, {:ok, session}} <- {:session, Authenticator.get_session(claims["jti"])} do
{:session, {:ok, session}} <- {:session, Authenticator.get_session(claims)} do
put_private(conn, :session, build_payload(session))
else
{:header, []} ->
Expand All @@ -38,10 +38,6 @@ defmodule RestAPI.Plugs.Authentication do
{:session, _any} ->
Logger.info("Session was not found")
Fallback.call(conn, {:error, :unauthenticated})

error ->
Logger.error("Failed to authenticate because of an unknow error")
Fallback.call(conn, error)
end
end

Expand Down
Loading