# RHI Magnesita - Web Template
# Configuration
## 1.1. Registering your Azure Application
- Navigate to the [Azure portal](https://go.microsoft.com/fwlink/?linkid=2083908&clcid=0x416) page.
- Select **New registration**.
- When the **Register an application** page appears, enter your application's registration information:
- In the **Name** section, enter **WebApp-OpenIDConnect-DotNet**
- In the **Supported account types** section, select **Accounts in any organizational directory**.
- In the **Redirect URI (optional)** section, select **Web** from the dropdown and enter the following URL: <br/>
```https://localhost:5000/signin-oidc```
- In the list of pages for the app, select **Authentication** and under **Advanced Settings**, set the **Logout URL** to following url and select **Save**:
```https://localhost:5000/signout-oidc```
- From the Azure portal, note the following information:
### Select **Register** to create the application.
- **The Tenant domain**: The base URL of your tenant directory. For example: *contoso.onmicrosoft.com*
- **The Tenant ID**: In the **Overview** blade, click on the the Endpoints link. Record the GUID from any of the endpoint URLs.<br/>
For example: *da41245a5-11b3-996c-00a8-4d99re19f292*
<br/>
The **Application (client) ID**: See the **Overview** blade and record the value.<br/>For example: *ba74781c2-53c2-442a-97c2-3d60re42f403*
[!NOTE] The base address in the **Sign-on URL** and **Logout URL** settings is *http://localhost:5000*.
This localhost address allows the sample app to run insecurely from your local system.<br/><br/>Port 5000 is the default port for the [Kestrel server](https://docs.microsoft.com/aspnet/core/fundamentals/servers/kestrel).
Update these URLs if you configure the app for production use (for example, *https://www.contoso.com/signin-oidc* and *https://www.contoso.com/signout-oidc*).
## 1.2. Creating your Azure Application
- Sign in [Azure portal](https://portal.azure.com/).
- Select **Azure Active Directory**.
- Click on **App Registrations**
- Click on **New Registration**
- Set a name for your Application and click on **Register** button.
Now, you've created and Application and it's time to configure your routes and get some very important information.
In Application Menu you'll see some sections like *Branding*, *Authentication*, *Certificates & Secrets* and many other options.
- In **Overview** section, you'll have an field called *Redirect URIs*. Once you still haven't a Redirect URI, let's configure it clicking on **Add a Redirect URI** link.
| Type | Redirect URI |
| --------- | ----------------------------------------------------------|
| Web | URL do servidor de identidade |
| Web | client_id obtido no registro de aplicação |
| Web | client_secret obtido no registro da aplicação |
| Web | Username informado no registro de usuários para aplicação |
| Web | Password informado no registro de usuários para aplicação |
Web https://CONSIDENTITY1.rhimagnesita.com:3001/swagger/oauth2-redirect.html (A porta é de acordo com o ambiente de homologação e produção)
Web https://CONSIDENTITY1.rhimagnesita.com:3001 (A porta é de acordo com o ambiente de homologação e produção)
Web https://localhost:3001/swagger/oauth2-redirect.html
Web https://localhost:3001
Web http://localhost:3000
Web http://localhost:3000/swagger/oauth2-redirect.html
- In the **Name** section, enter **WebApp-OpenIDConnect-DotNet**
- In the **Supported account types** section, select **Accounts in any organizational directory**.
- In the **Redirect URI (optional)** section, select **Web** from the dropdown and enter the following URL: <br/>
This sample was created from the 2.0 **dotnet new mvc** template with *SingleOrg* authentication. You can create the sample from the command line.
<br/>
To create the sample from the command line, execute the following command:
```
dotnet new mvc --auth SingleOrg --client-id <CLIENT_ID_(APP_ID)> --tenant-id <TENANT_ID> --domain <TENANT_DOMAIN>
```
Use the values that you recorded from the Azure portal for <CLIENT_ID_(APP_ID)>, <TENANT_ID>, and <TENANT_DOMAIN>.<br/><br/>
In the **appsettings.json** file, provide values for the *Domain*, *TenantId*, and *ClientID* that you recorded earlier from the Azure portal.
## 1.3. Running your Azure Application
Build the solution and run it.
Make a request to the app. The app immediately attempts to authenticate you via Azure AD. Sign in with the username and password of a user account that is in your Azure AD tenant. You can also use your tenant's Global Administrator account. If you wish to create a user in the tenant, select **Add a user** from the **Quick tasks** panel. The **Quick tasks** panel is found on the Azure AD tenant's blade in the portal.
### Requirements
Visual Studio Code
SDK 2.2 ou posterior do .NET Core
C# para Visual Studio Code
Visual Studio Code instructions use the .NET Core CLI for ASP.NET Core development functions, such as project creation. You can follow these instructions on any platform (macOS, Linux or Windows) and with any code editor. Minor changes may be required if you use something other than Visual Studio Code.
### Tutorial
This Microsoft tutorial explain about uses the WEB API. The architecture is the same that template works.

[Aspnet Core Tutorial - Web API](https://docs.microsoft.com/pt-br/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.2&tabs=visual-studio-code
)
Read each step and develop in template.
### About the Code
This sample shows how to use the OpenID Connect ASP.NET Core middleware to sign-in users from a single Azure AD tenant. The middleware is initialized in the *Startup.cs* file by passing it the Client ID of the app and the URL of the Azure AD tenant where the app is registered, which is read from the *appsettings.json* file. The middleware takes care of: - Downloading the Azure AD metadata, finding the signing keys, and finding the issuer name for the tenant. - Processing OpenID Connect sign-in responses by validating the signature and issuer in an incoming JWT, extracting the user's claims, and putting the claims in *ClaimsPrincipal.Current*. - Integrating with the session cookie ASP.NET Core middleware to establish a session for the user.
You can trigger the middleware to send an OpenID Connect sign-in request by decorating a class or method with the *[Authorize]* attribute or by issuing a challenge (see the *AccountController.cs* file):
```
return Challenge(
new AuthenticationProperties { RedirectUri = redirectUrl },
OpenIdConnectDefaults.AuthenticationScheme);
```
Similarly, you can send a signout request:
```
return SignOut(
new AuthenticationProperties { RedirectUri = callbackUrl },
CookieAuthenticationDefaults.AuthenticationScheme,
OpenIdConnectDefaults.AuthenticationScheme);
```
The middleware in this project is created as a part of the open source [ASP.NET Security](https://github.com/aspnet/Security) project.
# How To
## 2.1. Creating a project from Template
To Create your application, clone follow these instructions:
- Create a New Organization on AzureDevOps
- On the FISS Menu, go to "Templates" Organization.
- On the left side menu, choose "Repos" option.
- Click on "Clone", on the top right of page.
- Copy the link in 'HTTPS' Tab (by default, the 'HTTPS' is already selected)
- On your terminal, clone the Template repository by pasting the copied link:
```
$ git clone https://FISS@dev.azure.com/FISS/Templates/_git/TemplateWeb
```
- After clone the repo, open the project in a Code Editor ( We recommend VS Code because it have a high level of integrations with Git and Typescript).
### **2.1.1. Replace name occurrences, files and folders**
- Put the name of your application in .../ClientApp/src/config/app.json
- Replace the word "Template" by the name of your Application in all files and references.
- After replace occurrences in files, replace the name of your ***.csproj** files.
- After replace ***.csproj** files, replace the folder names.
- Last, replace all occurrences for "**rhi-template**" to "**rhi-[your_project_name]**"
```
Example: If your project was called "Admin"
Old name -> Rhi.Template...
rhi-template-...
New name -> Rhi.Admin...
rhi-admin-...
```
- After that, replace the '*tenant*', '*clientId*' and '*api*' by the data that you've received from Azure when you've created your Organization.
This replace must be applied in 3 files:
**Rhi.Sar.Web/ClientApp/src/config/azure-ad.json** <br/>
**Rhi.Sar.Web/appsettings.Development.json** <br/>
**Rhi.Sar.Web/appsettings.json**
- Replace the application name in file **Rhi.Sar.Web/ClientApp/src/config/app.json**
- OK, you've your project configured and now we need just to download the required dependencies to run our project:
Download required dependencies:
```
$ yarn deps
```
I you want to run only the front-end project
```
$ yarn front:start
```
To run the back-end project
```
$ yarn back:start
```
This scripts are in ./package.json
## 2.2. Create a new page
To Create a page, follow these tips:
- Create a new folder with the name of the Page. Use [Pascal Case](http://wiki.c2.com/?PascalCase) to name it. (E.g: **TutorialPage**)
- Create a file called **"index.tsx"** into created page. Your code will be writed in this file.
- Import React class into your page.<br /><br />
**TutorialPage/index.tsx:**
```
import React from 'react';
```
<br /><br />
- Add an export into your file:
```
import React from 'react';
export default () => {
return(
<h1>Welcome to Tutorial Page!</h1>
);
}
```
This way, your page can be imported in other files<br /><br />
- Add your page into **'.../ClientApp/src/views/index.ts'** file
```
export { default as Products } from './Home';
export { default as Items } from './NotFound';
export { default as Shop } from './User';
export { default as TutorialPage } from './TutorialPage'; // <- Your page
```
- Create a menu item and a route for your Page into **'.../ClientApp/src/config/menu.json'** file
```
{
"topArea": [],
"menu": [
{ "label": "User Name", "icon": "profile-gender_neutral_user" },
{
"label": "Administration",
"icon": "commons-settings",
"items": [
{ "label": "Products", "uri": "/products" },
{ "label": "Items", "uri": "/items" },
{ "label": "Shop", "uri": "/shop" },
{ "label": "Tutorial Page", "uri": "/tutorial" }
]
},
{ "label": "Infoboards", "icon": "data-data_sheet" },
{ "label": "Documentation", "icon": "data-activity_feed" }
],
"routes": ["/products", "/items", "/shop", "/tutorial"]
}
```
<br /><br />
- Register your Page into **'src/App.tsx'** file
```
import models from '@app/store/models';
import { Products, Items, Shop, TutorialPage } from './views';
import menuData from './menu.json';
const headerData = { logo: Logo, title: 'SYSTEM NAME' };
const routes = [
{ uri: '/products', component: Products },
{ uri: '/items', component: Items },
{ uri: '/shop', component: Shop },
{ uri: '/tutorial', component: TutorialPage },
];
export default () => (
<AppContainer models={models} header={headerData}>
<Router>
<Workspace menu={menuData as React.ComponentProps<typeof Workspace>['menu']}>
<Switch>
<Route path="/" exact component={Home} />
{routes
.filter(route => menuData.routes.includes(route.uri))
.map(route => (
<Route key={route.uri} path={route.uri} component={route.component} />
))}
<Route component={NotFound} />
</Switch>
</Workspace>
</Router>
</AppContainer>
);
```
After that, your page will be accessible on browser!
### Testing our page
And then let's run the project
```
$ yarn rhi-template:dev
```
# Authentication
## 3.1. Protecting your API
The **Identity Server** emit access tokens in [JWT](https://jwt.io) (JSON Web Token) format.
Nowadays, the most relevant Software Development Application Platforms provides support for JWT token validation. Here are some popular libraries:
1. [Microsoft.AspNetCore.Authentication.JwtBearer](https://www.nuget.org/packages/Microsoft.AspNetCore.Authentication.JwtBearer) para ASP.NET Core
2. [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) for Node.js
3. [java-jwt](https://github.com/auth0/java-jwt) for Java
## 3.2. Obtendo um token de acesso
O **Identity Server** permite as seguintes formas de obtenção do token de acesso:
1. **Resource owner password**: permite obter o token de acesso para usuários de forma "não-interativa" através de usuário e senha.
2. **Client credentials**: permite obter o token de acesso para aplicações. Utilizada para authentication
<!-- 3. **Delegation**: permite a transformação de um token de acesso para outro de acordo com suas permissões. Utilizada para comunicação entre aplicações. -->
### **3.2.1. Resource owner password - obtendo um token de acesso para usuários**
* Requisição
```
curl --request POST
--url {IDENTITY_SERVER_URL}/connect/token
--form grant_type=password
--form client_id={CLIENT_ID}
--form client_secret={CLIENT_SECRET}
--form scope={CLIENT_ID}
--form username={USERNAME}
--form password={PASSWORD}
```
| Parâmetro | aescrição |
| :------------------ | :-------------------------------------------------------- |
| IDENTITY_SERVER_URL | URL do servidor de identidade |
| CLIENT_ID | client_id obtido no registro de aplicação |
| CLIENT_SECRET | client_secret obtido no registro da aplicação |
| USERNAME | Username informado no registro de usuários para aplicação |
| PASSWORD | Password informado no registro de usuários para aplicação |
* Resposta
```
{
"access_token": "{TOKEN}",
"expires_in": 3600,
"token_type": "Bearer"
}
```
| Parâmetro | Descrição |
| :-------- | :------------------------------------------------------- |
| TOKEN | Token de acesso que deverá ser utilizado nas requisições |
### **3.2.2. Client credentials - obtendo um token de acesso para sistemas**
* Requisição
```
curl --request POST
--url {IDENTITY_SERVER_URL}/connect/token
--form grant_type=client_credentials
--form client_id={CLIENT_ID}
--form client_secret={CLIENT_SECRET}
--form scope={CLIENT_ID}
```
| Parâmetro | Descrição |
| :------------------ | :-------------------------------------------- |
| IDENTITY_SERVER_URL | URL do servidor de identidade |
| CLIENT_ID | client_id obtido no registro de aplicação |
| CLIENT_SECRET | client_secret obtido no registro da aplicação |
* Resposta
```
{
"access_token": "{TOKEN}",
"expires_in": 3600,
"token_type": "Bearer"
}
```
| Parâmetro | Descrição |
| :-------- | :------------------------------------------------------- |
| TOKEN | Token de acesso que deverá ser utilizado nas requisições |
## 3.3. Informações do token
O token JWT é composto por 3 partes: Header, Payload e Signature.
O Payload contém dados importantes para controle dentro das aplicações e sua estrutura pode ser decodificada de forma transparente pelas bibliotecas de cada plataforma.
A seguir é mostrado a estrutura para cada tipo específico de token mostrando os atributos disponíveis para cada um deles.
### 3.3.1. Token de usuário
```
{
"nbf": {NBF},
"exp": {EXP},
"iss": {ISS},
"aud": {AUD},
"client_id": {CLIENT_ID},
"sub": {SUB},
"auth_time": {AUTH_TIME},
"idp": {IDP},
"name": {NAME},
"email": {EMAIL},
"role": {ROLE},
"scope": {SCOPE},
"amr": {AMR}
}
```
| Parâmetro | Descrição | Tipo |
| :-------- | :---------------------------------------- | :-------------------------------- |
| NBF | Data de início da validade do token | number (seconds since unix epoch) |
| EXP | Data de expiração do token | number (seconds since unix epoch) |
| ISS | Emissor do token | string |
| AUD | Audiência para o qual o token é destinado | array |
| CLIENT_ID | client_id para o qual o token foi emitido | string |
| SUB | identificador único do usuário | string |
| AUTH_TIME | Data da geração do token | string |
| IDP | Provedor de identidade | string |
| NAME | Nome do usuário | string |
| EMAIL | Email do usuário | string |
| ROLE | Roles do usuário | string or array |
| SCOPE | Escopos contemplados pelo token | array |
| AMR | Método de Authentication
### 3.3.1. Token de sistema
```
{
"nbf": {NBF},
"exp": {EXP},
"iss": {ISS},
"aud": {AUD},
"client_id": {CLIENT_ID},
"scope": {SCOPE}
}
```
| Parâmetro | Descrição | Tipo |
| :-------- | :---------------------------------------- | :-------------------------------- |
| NBF | Data de início da validade do token | number (seconds since unix epoch) |
| EXP | Data de expiração do token | number (seconds since unix epocha |
| ISS | Emissor do token | string |
| AUD | Audiência para o qual o token é destinado | array |
| CLIENT_ID | client_id para o qual o token foi emitido | string |
| SCOPE | Escopos contemplados pelo token | array |