mirror of https://github.com/abpframework/abp.git
committed by
GitHub
740 changed files with 203104 additions and 33 deletions
@ -0,0 +1,240 @@ |
|||
## ABP OpenIddict Modules |
|||
|
|||
## How to Install |
|||
|
|||
TODO: |
|||
|
|||
## User Interface |
|||
|
|||
This module implements the domain logic and database integrations, but not provides any UI. Management UI is useful if you need to add applications and scopes on the fly. In this case, you may build the management UI yourself or consider to purchase the [ABP Commercial](https://commercial.abp.io/) which provides the management UI for this module. |
|||
|
|||
## Relations to Other Modules |
|||
|
|||
This module is based on the [Identity Module](Identity.md) and have an [integration package](https://www.nuget.org/packages/Volo.Abp.Account.Web.IdentityServer) with the [Account Module](Account.md). |
|||
|
|||
## The module |
|||
|
|||
### Demo projects |
|||
|
|||
In the module's `app` directory there are six projects(including `angular`) |
|||
|
|||
* `OpenIddict.Demo.Server`: An abp application with integrated modules (has two `clients` and a `scope`). |
|||
* `OpenIddict.Demo.API`: ASP NET Core API application using JwtBearer authentication |
|||
* `OpenIddict.Demo.Client.Mvc`: ASP NET Core MVC application using `OpenIdConnect` for authentication |
|||
* `OpenIddict.Demo.Client.Console`: Use `IdentityModel` to test OpenIddict's various endpoints, and call the api of `OpenIddict.Demo.API` |
|||
* `OpenIddict.Demo.Client.BlazorWASM:` ASP NET Core Blazor application using `OidcAuthentication` for authentication |
|||
* `angular`: An angular application that integrates the abp ng modules and uses oauth for authentication |
|||
|
|||
#### How to run? |
|||
|
|||
Confirm the connection string of `appsettings.json` in the `OpenIddict.Demo.Server` project. Running the project will automatically create the database and initialize the data. |
|||
After running the `OpenIddict.Demo.API` project, then you can run the rest of the projects to test. |
|||
|
|||
### Domain module |
|||
|
|||
There are four main entities included in this module. |
|||
|
|||
* OpenIddictApplication: **Represents applications(client)** |
|||
* OpenIddictScope: **Represents scopes** |
|||
* OpenIddictAuthorization: **Represents authorizations, Track of logical chains of tokens and user consent..** |
|||
* OpenIddictToken: **Represents various tokens.** |
|||
|
|||
Domain also implements four store interfaces in OpenIddict, OpenIddict uses store to manage entities, corresponding to the above four entities, Custom entity repository is used in the store. |
|||
|
|||
|
|||
```cs |
|||
//Manager |
|||
OpenIddictApplicationManager |
|||
OpenIddictScopeManager |
|||
OpenIddictAuthorizationManager |
|||
OpenIddictTokenManager |
|||
|
|||
//Store |
|||
IOpenIddictApplicationStore |
|||
IOpenIddictScopeStore |
|||
IOpenIddictAuthorizationStore |
|||
IOpenIddictTokenStore |
|||
|
|||
//Repository |
|||
IOpenIddictApplicationRepository |
|||
IOpenIddictScopeRepository |
|||
IOpenIddictAuthorizationRepository |
|||
IOpenIddictTokenRepository |
|||
``` |
|||
|
|||
We enabled most of OpenIddict's features in the `AddOpenIddict` method, You can change OpenIddict's related builder options via `PreConfigure`. |
|||
|
|||
```cs |
|||
PreConfigure<OpenIddictBuilder>(builder => |
|||
{ |
|||
//builder |
|||
}); |
|||
|
|||
PreConfigure<OpenIddictCoreBuilder>(builder => |
|||
{ |
|||
//builder |
|||
}); |
|||
|
|||
PreConfigure<OpenIddictServerBuilder>(builder => |
|||
{ |
|||
//builder |
|||
}); |
|||
``` |
|||
|
|||
#### AbpOpenIddictOptions |
|||
|
|||
`UpdateAbpClaimTypes(default: true)`: Updates AbpClaimTypes to be compatible with identity server claims. |
|||
`AddDevelopmentEncryptionAndSigningCertificate(default: true)`: Registers (and generates if necessary) a user-specific development encryption/development signing certificate. |
|||
|
|||
You can also change this options via `PreConfigure`. |
|||
|
|||
#### Automatically removing orphaned tokens/authorizations |
|||
|
|||
There is a background task in the `Domain` module (`enabled by default`) that automatically removes orphaned tokens/authorizations, you can configure `TokenCleanupOptions` to manage it. |
|||
|
|||
### ASP NET Core module |
|||
|
|||
This module integrates ASP NET Core, with built-in MVC controllers for four protocols. It uses OpenIddict's [Pass-through mode](https://documentation.openiddict.com/guides/index.html#pass-through-mode). |
|||
|
|||
```cs |
|||
AuthorizeController -> connect/authorize |
|||
TokenController -> connect/token |
|||
LogoutController -> connect/logout |
|||
UserInfoController -> connect/userinfo |
|||
``` |
|||
|
|||
> We will implement the related functions of **device flow** in the PRO module.. |
|||
|
|||
#### How to control claims in access_token and id_token |
|||
|
|||
You can use the [Claims Principal Factory](https://docs.abp.io/en/abp/latest/Authorization#claims-principal-factory) to add/remove claims to the `ClaimsPrincipal`. |
|||
|
|||
The `AbpDefaultOpenIddictClaimDestinationsProvider` service will add `Name`, `Email` and `Role` types of Claims to `access_token` and `id_token`, other claims are only added to `access_token` by default, and remove the `SecurityStampClaimType` secret claim of `Identity`. |
|||
|
|||
You can create a service that inherits from `IAbpOpenIddictClaimDestinationsProvider` and add it to DI to fully control the destinations of claims |
|||
|
|||
```cs |
|||
public class MyClaimDestinationsProvider : IAbpOpenIddictClaimDestinationsProvider, ITransientDependency |
|||
{ |
|||
public virtual Task SetDestinationsAsync(AbpOpenIddictClaimDestinationsProviderContext context) |
|||
{ |
|||
// ... |
|||
return Task.CompletedTask; |
|||
} |
|||
} |
|||
|
|||
Configure<AbpOpenIddictClaimDestinationsOptions>(options => |
|||
{ |
|||
options.ClaimDestinationsProvider.Add<MyClaimDestinationsProvider>(); |
|||
}); |
|||
``` |
|||
|
|||
For detailed information, please refer to: [OpenIddict claim destinations](https://documentation.openiddict.com/configuration/claim-destinations.html) |
|||
|
|||
#### About Validation |
|||
|
|||
The `OpenIddict.Validation.AspNetCore` and `OpenIddict.Validation` are not integrated in the module, we use the authentication component provided by Microsoft. If you are more familiar with it, you can use it in your project. |
|||
|
|||
|
|||
### EF Core module |
|||
|
|||
Implements the above four repository interfaces. |
|||
|
|||
### MongoDB module |
|||
|
|||
Implements the above four repository interfaces. |
|||
|
|||
|
|||
## OpenIddict |
|||
|
|||
### Documentation |
|||
|
|||
For more details about OpenIddict, please refer to its official documentation and Github. |
|||
|
|||
https://documentation.openiddict.com |
|||
|
|||
https://github.com/openiddict/openiddict-core#resources |
|||
|
|||
### Token encryption |
|||
|
|||
https://documentation.openiddict.com/configuration/encryption-and-signing-credentials.html |
|||
|
|||
> By default, OpenIddict enforces encryption for all the token types it supports. While this enforcement cannot be disabled for authorization codes, refresh tokens and device codes for security reasons, it can be relaxed for access tokens when integration with third-party APIs/resource servers is desired. Access token encryption can also be disabled if the resource servers receiving the access tokens don't fully support JSON Web Encryption. |
|||
|
|||
```cs |
|||
PreConfigure<OpenIddictServerBuilder>(builder => |
|||
{ |
|||
builder.DisableAccessTokenEncryption(); |
|||
}); |
|||
``` |
|||
|
|||
An example of using `SecurityKey` |
|||
|
|||
> In production, it is recommended to use two RSA certificates, distinct from the certificate(s) used for HTTPS: one for encryption, one for signing. |
|||
|
|||
```cs |
|||
// In OpenIddict Server |
|||
PreConfigure<OpenIddictServerBuilder>(builder => |
|||
{ |
|||
builder.AddSigningKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78"))); |
|||
builder.AddEncryptionKey(new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80"))); |
|||
}); |
|||
|
|||
//In Client AddJwtBearer |
|||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |
|||
.AddJwtBearer(options => |
|||
{ |
|||
//Other configuration |
|||
|
|||
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78")); |
|||
options.TokenValidationParameters.TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80")); |
|||
}); |
|||
``` |
|||
|
|||
|
|||
### PKCE |
|||
|
|||
https://documentation.openiddict.com/configuration/proof-key-for-code-exchange.html |
|||
|
|||
### Request/Response process |
|||
|
|||
I will briefly introduce the principle of OpenIddict so that everyone can quickly understand it. |
|||
|
|||
The `OpenIddict.Server.AspNetCore` adds an authentication scheme(`Name: OpenIddict.Server.AspNetCore, handler: OpenIddictServerAspNetCoreHandler`) and implements the `IAuthenticationRequestHandler` interface. |
|||
|
|||
It will be executed first in `AuthenticationMiddleware` and can short-circuit the current request. Otherwise, `DefaultAuthenticateScheme` will be called and continue to execute the pipeline. |
|||
|
|||
`OpenIddictServerAspNetCoreHandler` will call various built-in handlers(Handling requests and responses), And the handler will process according to the context or skip logic that has nothing to do with it. |
|||
|
|||
Example a token request: |
|||
|
|||
``` |
|||
POST /connect/token HTTP/1.1 |
|||
Content-Type: application/x-www-form-urlencoded |
|||
|
|||
grant_type=password& |
|||
client_id=AbpApp& |
|||
client_secret=1q2w3e*& |
|||
username=admin& |
|||
password=1q2w3E*& |
|||
scope=AbpAPI offline_access |
|||
``` |
|||
|
|||
This request will be processed by various handlers. They will confirm the endpoint type of the request, check `http/https`, verify that the request parameters (`client. scope etc`) are valid and exist in the database, etc. Various protocol checks. And build a `OpenIddictRequest` object, If there are any errors, the response content may be set and directly short-circuit the current request. |
|||
|
|||
If everything is ok, the request will go to our processing controller(eg `TokenController`), we can get an `OpenIddictRequest` from the http request at this time. The rest of our work will be based on this object. |
|||
|
|||
We may check the `username` and `password` in the request. If it is correct we create a `ClaimsPrincipal` object and return a `SignInResult`, which uses the `OpenIddict.Validation.AspNetCore` authentication scheme name, will calls `OpenIddictServerAspNetCoreHandler` for processing. |
|||
|
|||
`OpenIddictServerAspNetCoreHandler` do some checks to generate json and replace the http response content. |
|||
|
|||
The `ForbidResult` `ChallengeResult` are all the above types of processing. |
|||
|
|||
If you need to customize OpenIddict, you need to replace/delete/add new handlers and make it execute in the correct order. |
|||
|
|||
Please refer to: |
|||
https://documentation.openiddict.com/guides/index.html#events-model |
|||
|
|||
## Sponsor |
|||
|
|||
Please consider sponsoring this project: https://github.com/sponsors/kevinchalet |
|||
@ -1,27 +0,0 @@ |
|||
{ |
|||
"iisSettings": { |
|||
"windowsAuthentication": false, |
|||
"anonymousAuthentication": true, |
|||
"iisExpress": { |
|||
"applicationUrl": "http://localhost:2922/", |
|||
"sslPort": 44394 |
|||
} |
|||
}, |
|||
"profiles": { |
|||
"IIS Express": { |
|||
"commandName": "IISExpress", |
|||
"launchBrowser": true, |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
}, |
|||
"Volo.Abp.Account.Web.IdentityServer": { |
|||
"commandName": "Project", |
|||
"launchBrowser": true, |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
}, |
|||
"applicationUrl": "https://localhost:5001;http://localhost:5000" |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.OpenIddict; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace Volo.Abp.Account.Web; |
|||
|
|||
[DependsOn( |
|||
typeof(AbpAccountWebModule), |
|||
typeof(AbpOpenIddictAspNetCoreModule) |
|||
)] |
|||
public class AbpAccountWebOpenIddictModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure<IMvcBuilder>(mvcBuilder => |
|||
{ |
|||
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountWebOpenIddictModule).Assembly); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<AbpAccountWebOpenIddictModule>(); |
|||
}); |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
|||
<ConfigureAwait ContinueOnCapturedContext="false" /> |
|||
</Weavers> |
|||
@ -0,0 +1,30 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
|||
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
|||
<xs:element name="Weavers"> |
|||
<xs:complexType> |
|||
<xs:all> |
|||
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
|||
<xs:complexType> |
|||
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:all> |
|||
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
|||
<xs:annotation> |
|||
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
|||
<xs:annotation> |
|||
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
|||
</xs:annotation> |
|||
</xs:attribute> |
|||
</xs:complexType> |
|||
</xs:element> |
|||
</xs:schema> |
|||
@ -0,0 +1,114 @@ |
|||
using System; |
|||
using System.Security.Claims; |
|||
using System.Threading.Tasks; |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.Extensions.Options; |
|||
using Microsoft.AspNetCore.Identity; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using OpenIddict.Server; |
|||
using OpenIddict.Server.AspNetCore; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.OpenIddict; |
|||
|
|||
namespace Volo.Abp.Account.Web.Pages.Account; |
|||
|
|||
[ExposeServices(typeof(LoginModel))] |
|||
public class OpenIddictSupportedLoginModel : LoginModel |
|||
{ |
|||
protected AbpOpenIddictRequestHelper OpenIddictRequestHelper { get; } |
|||
public OpenIddictSupportedLoginModel( |
|||
IAuthenticationSchemeProvider schemeProvider, |
|||
IOptions<AbpAccountOptions> accountOptions, |
|||
IOptions<IdentityOptions> identityOptions, |
|||
AbpOpenIddictRequestHelper openIddictRequestHelper) |
|||
: base(schemeProvider, accountOptions, identityOptions) |
|||
{ |
|||
OpenIddictRequestHelper = openIddictRequestHelper; |
|||
} |
|||
|
|||
public async override Task<IActionResult> OnGetAsync() |
|||
{ |
|||
LoginInput = new LoginInputModel(); |
|||
|
|||
var request = await OpenIddictRequestHelper.GetFromReturnUrlAsync(ReturnUrl); |
|||
if (request?.ClientId != null) |
|||
{ |
|||
ShowCancelButton = true; |
|||
|
|||
LoginInput.UserNameOrEmailAddress = request.LoginHint; |
|||
|
|||
//TODO: Reference AspNetCore MultiTenancy module and use options to get the tenant key!
|
|||
var tenant = request.GetParameter(TenantResolverConsts.DefaultTenantKey)?.ToString(); |
|||
if (!string.IsNullOrEmpty(tenant)) |
|||
{ |
|||
CurrentTenant.Change(Guid.Parse(tenant)); |
|||
Response.Cookies.Append(TenantResolverConsts.DefaultTenantKey, tenant); |
|||
} |
|||
} |
|||
|
|||
return await base.OnGetAsync(); |
|||
} |
|||
|
|||
public async override Task<IActionResult> OnPostAsync(string action) |
|||
{ |
|||
if (action == "Cancel") |
|||
{ |
|||
var request = await OpenIddictRequestHelper.GetFromReturnUrlAsync(ReturnUrl); |
|||
|
|||
var transaction = HttpContext.GetOpenIddictServerTransaction(); |
|||
if (request?.ClientId != null && transaction != null) |
|||
{ |
|||
transaction.EndpointType = OpenIddictServerEndpointType.Authorization; |
|||
transaction.Request = request; |
|||
|
|||
var notification = new OpenIddictServerEvents.ValidateAuthorizationRequestContext(transaction); |
|||
transaction.SetProperty(typeof(OpenIddictServerEvents.ValidateAuthorizationRequestContext).FullName!, notification); |
|||
|
|||
return Forbid(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); |
|||
} |
|||
|
|||
return Redirect("~/"); |
|||
} |
|||
|
|||
return await base.OnPostAsync(action); |
|||
} |
|||
|
|||
public async override Task<IActionResult> OnPostExternalLogin(string provider) |
|||
{ |
|||
if (AccountOptions.WindowsAuthenticationSchemeName == provider) |
|||
{ |
|||
return await ProcessWindowsLoginAsync(); |
|||
} |
|||
|
|||
return await base.OnPostExternalLogin(provider); |
|||
} |
|||
|
|||
protected virtual async Task<IActionResult> ProcessWindowsLoginAsync() |
|||
{ |
|||
var result = await HttpContext.AuthenticateAsync(AccountOptions.WindowsAuthenticationSchemeName); |
|||
if (result.Succeeded) |
|||
{ |
|||
var props = new AuthenticationProperties() |
|||
{ |
|||
RedirectUri = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash }), |
|||
Items = |
|||
{ |
|||
{ |
|||
"LoginProvider", AccountOptions.WindowsAuthenticationSchemeName |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var id = new ClaimsIdentity(AccountOptions.WindowsAuthenticationSchemeName); |
|||
id.AddClaim(new Claim(ClaimTypes.NameIdentifier, result.Principal.FindFirstValue(ClaimTypes.PrimarySid))); |
|||
id.AddClaim(new Claim(ClaimTypes.Name, result.Principal.FindFirstValue(ClaimTypes.Name))); |
|||
|
|||
await HttpContext.SignInAsync(IdentityConstants.ExternalScheme, new ClaimsPrincipal(id), props); |
|||
|
|||
return Redirect(props.RedirectUri!); |
|||
} |
|||
|
|||
return Challenge(AccountOptions.WindowsAuthenticationSchemeName); |
|||
} |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bootstrap |
|||
@addTagHelper *, Volo.Abp.AspNetCore.Mvc.UI.Bundling |
|||
@ -0,0 +1,34 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<Import Project="..\..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<AssemblyName>Volo.Abp.Account.Web.OpenIddict</AssemblyName> |
|||
<PackageId>Volo.Abp.Account.Web.OpenIddict</PackageId> |
|||
<IsPackable>true</IsPackable> |
|||
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback> |
|||
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
|||
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
|||
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
|||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest> |
|||
<RootNamespace>Volo.Abp.Account.Web</RootNamespace> |
|||
<OutputType>Library</OutputType> |
|||
</PropertyGroup> |
|||
|
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\..\openiddict\src\Volo.Abp.OpenIddict.AspNetCore\Volo.Abp.OpenIddict.AspNetCore.csproj" /> |
|||
<ProjectReference Include="..\Volo.Abp.Account.Web\Volo.Abp.Account.Web.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="System.Security.Principal.Windows" Version="5.0.0" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="$(MicrosoftPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,5 @@ |
|||
{ |
|||
"singleQuote": true, |
|||
"useTabs": false, |
|||
"tabWidth": 4 |
|||
} |
|||
@ -0,0 +1,132 @@ |
|||
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00 |
|||
# Visual Studio Version 16 |
|||
VisualStudioVersion = 16.0.29001.49 |
|||
MinimumVisualStudioVersion = 10.0.40219.1 |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.Domain.Shared", "src\Volo.Abp.OpenIddict.Domain.Shared\Volo.Abp.OpenIddict.Domain.Shared.csproj", "{D64C1577-4929-4B60-939E-96DE1534891A}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.Domain", "src\Volo.Abp.OpenIddict.Domain\Volo.Abp.OpenIddict.Domain.csproj", "{F2840BC7-0188-4606-9126-DADD0F5ABF7A}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{649A3FFA-182F-4E56-9717-E6A9A2BEC545}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.EntityFrameworkCore", "src\Volo.Abp.OpenIddict.EntityFrameworkCore\Volo.Abp.OpenIddict.EntityFrameworkCore.csproj", "{0CE86223-D31D-4315-A1F5-87BA3EE1B844}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.MongoDB", "src\Volo.Abp.OpenIddict.MongoDB\Volo.Abp.OpenIddict.MongoDB.csproj", "{F1C58097-4C08-4D88-8976-6B3389391481}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.TestBase", "test\Volo.Abp.OpenIddict.TestBase\Volo.Abp.OpenIddict.TestBase.csproj", "{C5BB573D-3030-4BCB-88B7-F6A85C32766C}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.EntityFrameworkCore.Tests", "test\Volo.Abp.OpenIddict.EntityFrameworkCore.Tests\Volo.Abp.OpenIddict.EntityFrameworkCore.Tests.csproj", "{527F645C-C1FC-406E-8479-81386C8ECF13}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.MongoDB.Tests", "test\Volo.Abp.OpenIddict.MongoDB.Tests\Volo.Abp.OpenIddict.MongoDB.Tests.csproj", "{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}" |
|||
EndProject |
|||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.OpenIddict.Domain.Tests", "test\Volo.Abp.OpenIddict.Domain.Tests\Volo.Abp.OpenIddict.Domain.Tests.csproj", "{E60895E5-79C4-447D-88B7-85CB5BA336A4}" |
|||
EndProject |
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "app", "app", "{2B5CD179-FF7B-428F-98F6-2ADBB9538D18}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIddict.Demo.Server", "app\OpenIddict.Demo.Server\OpenIddict.Demo.Server.csproj", "{88FD6C42-4134-4F35-A104-ED8520463847}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIddict.Demo.Client.Mvc", "app\OpenIddict.Demo.Client.Mvc\OpenIddict.Demo.Client.Mvc.csproj", "{FC1F7510-047E-4D4B-B024-82BB5269E584}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.OpenIddict.AspNetCore", "src\Volo.Abp.OpenIddict.AspNetCore\Volo.Abp.OpenIddict.AspNetCore.csproj", "{2DCC3E87-4901-4980-ABB8-0A93F2C2F7B8}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIddict.Demo.Client.Console", "app\OpenIddict.Demo.Client.Console\OpenIddict.Demo.Client.Console.csproj", "{1EF0F35E-65BE-4994-9BC4-9D3992A9B05C}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIddict.Demo.API", "app\OpenIddict.Demo.API\OpenIddict.Demo.API.csproj", "{70FD6E90-BBE8-4DA1-AE07-55064803225B}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenIddict.Demo.Client.BlazorWASM", "app\OpenIddict.Demo.Client.BlazorWASM\OpenIddict.Demo.Client.BlazorWASM.csproj", "{F3853F2B-72D4-496C-B59C-87E2759AD79B}" |
|||
EndProject |
|||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.Domain.OpenIddict", "src\Volo.Abp.PermissionManagement.Domain.OpenIddict\Volo.Abp.PermissionManagement.Domain.OpenIddict.csproj", "{674D0A62-4F7B-436C-83A9-AA8FE03F3A11}" |
|||
EndProject |
|||
Global |
|||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
|||
Debug|Any CPU = Debug|Any CPU |
|||
Release|Any CPU = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{D64C1577-4929-4B60-939E-96DE1534891A}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F1C58097-4C08-4D88-8976-6B3389391481}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{88FD6C42-4134-4F35-A104-ED8520463847}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{88FD6C42-4134-4F35-A104-ED8520463847}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{88FD6C42-4134-4F35-A104-ED8520463847}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{88FD6C42-4134-4F35-A104-ED8520463847}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{FC1F7510-047E-4D4B-B024-82BB5269E584}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{FC1F7510-047E-4D4B-B024-82BB5269E584}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{FC1F7510-047E-4D4B-B024-82BB5269E584}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{FC1F7510-047E-4D4B-B024-82BB5269E584}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{2DCC3E87-4901-4980-ABB8-0A93F2C2F7B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{2DCC3E87-4901-4980-ABB8-0A93F2C2F7B8}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{2DCC3E87-4901-4980-ABB8-0A93F2C2F7B8}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{2DCC3E87-4901-4980-ABB8-0A93F2C2F7B8}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{1EF0F35E-65BE-4994-9BC4-9D3992A9B05C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{1EF0F35E-65BE-4994-9BC4-9D3992A9B05C}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{1EF0F35E-65BE-4994-9BC4-9D3992A9B05C}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{1EF0F35E-65BE-4994-9BC4-9D3992A9B05C}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{70FD6E90-BBE8-4DA1-AE07-55064803225B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{70FD6E90-BBE8-4DA1-AE07-55064803225B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{70FD6E90-BBE8-4DA1-AE07-55064803225B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{70FD6E90-BBE8-4DA1-AE07-55064803225B}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{F3853F2B-72D4-496C-B59C-87E2759AD79B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{F3853F2B-72D4-496C-B59C-87E2759AD79B}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{F3853F2B-72D4-496C-B59C-87E2759AD79B}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{F3853F2B-72D4-496C-B59C-87E2759AD79B}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
{674D0A62-4F7B-436C-83A9-AA8FE03F3A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
|||
{674D0A62-4F7B-436C-83A9-AA8FE03F3A11}.Debug|Any CPU.Build.0 = Debug|Any CPU |
|||
{674D0A62-4F7B-436C-83A9-AA8FE03F3A11}.Release|Any CPU.ActiveCfg = Release|Any CPU |
|||
{674D0A62-4F7B-436C-83A9-AA8FE03F3A11}.Release|Any CPU.Build.0 = Release|Any CPU |
|||
EndGlobalSection |
|||
GlobalSection(SolutionProperties) = preSolution |
|||
HideSolutionNode = FALSE |
|||
EndGlobalSection |
|||
GlobalSection(NestedProjects) = preSolution |
|||
{D64C1577-4929-4B60-939E-96DE1534891A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{F2840BC7-0188-4606-9126-DADD0F5ABF7A} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{0CE86223-D31D-4315-A1F5-87BA3EE1B844} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{F1C58097-4C08-4D88-8976-6B3389391481} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{C5BB573D-3030-4BCB-88B7-F6A85C32766C} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{527F645C-C1FC-406E-8479-81386C8ECF13} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{D0AD9179-125C-40B2-A8EE-CD4C1EE24BB6} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{E60895E5-79C4-447D-88B7-85CB5BA336A4} = {CCD2960C-23CC-4AB4-B84D-60C7AAA52F4D} |
|||
{88FD6C42-4134-4F35-A104-ED8520463847} = {2B5CD179-FF7B-428F-98F6-2ADBB9538D18} |
|||
{FC1F7510-047E-4D4B-B024-82BB5269E584} = {2B5CD179-FF7B-428F-98F6-2ADBB9538D18} |
|||
{2DCC3E87-4901-4980-ABB8-0A93F2C2F7B8} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
{1EF0F35E-65BE-4994-9BC4-9D3992A9B05C} = {2B5CD179-FF7B-428F-98F6-2ADBB9538D18} |
|||
{70FD6E90-BBE8-4DA1-AE07-55064803225B} = {2B5CD179-FF7B-428F-98F6-2ADBB9538D18} |
|||
{F3853F2B-72D4-496C-B59C-87E2759AD79B} = {2B5CD179-FF7B-428F-98F6-2ADBB9538D18} |
|||
{674D0A62-4F7B-436C-83A9-AA8FE03F3A11} = {649A3FFA-182F-4E56-9717-E6A9A2BEC545} |
|||
EndGlobalSection |
|||
GlobalSection(ExtensibilityGlobals) = postSolution |
|||
SolutionGuid = {C09128AF-C73F-ED7D-33F5-69BF7D934D50} |
|||
EndGlobalSection |
|||
EndGlobal |
|||
@ -0,0 +1,23 @@ |
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> |
|||
<s:Boolean x:Key="/Default/CodeEditing/Intellisense/CodeCompletion/IntelliSenseCompletingCharacters/CSharpCompletingCharacters/UpgradedFromVSSettings/@EntryValue">True</s:Boolean> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceDoWhileStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceFixedStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForeachStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceForStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceIfStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceLockStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceUsingStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=EnforceWhileStatementBraces/@EntryIndexedValue">WARNING</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOR/@EntryValue">Required</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_FOREACH/@EntryValue">Required</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_IFELSE/@EntryValue">Required</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_FOR_WHILE/@EntryValue">Required</s:String> |
|||
<s:Boolean x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/BRACES_REDUNDANT/@EntryValue">False</s:Boolean> |
|||
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Implementations/@KeyIndexDefined">True</s:Boolean> |
|||
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Async/@EntryIndexedValue">False</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Generate/=Implementations/Options/=Mutable/@EntryIndexedValue">False</s:String> |
|||
<s:Boolean x:Key="/Default/CodeStyle/Generate/=Overrides/@KeyIndexDefined">True</s:Boolean> |
|||
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Async/@EntryIndexedValue">False</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Generate/=Overrides/Options/=Mutable/@EntryIndexedValue">False</s:String> |
|||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SQL/@EntryIndexedValue">SQL</s:String> |
|||
</wpf:ResourceDictionary> |
|||
@ -0,0 +1,16 @@ |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
|
|||
namespace OpenIddict.Demo.API.Controllers; |
|||
|
|||
[ApiController] |
|||
[Authorize] |
|||
[Route("api/claims")] |
|||
public class ClaimsController : Controller |
|||
{ |
|||
[HttpGet] |
|||
public JsonResult Get() |
|||
{ |
|||
return Json(User.Claims.Select(x => new {Type = x.Type, Value = x.Value})); |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.3" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,43 @@ |
|||
using System.Text; |
|||
using Microsoft.AspNetCore.Authentication.JwtBearer; |
|||
using Microsoft.IdentityModel.Tokens; |
|||
|
|||
var builder = WebApplication.CreateBuilder(args); |
|||
builder.Logging.ClearProviders(); |
|||
builder.Logging.AddConsole(); |
|||
|
|||
// Add services to the container.
|
|||
|
|||
builder.Services.AddControllers(); |
|||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
|||
builder.Services.AddEndpointsApiExplorer(); |
|||
builder.Services.AddSwaggerGen(); |
|||
|
|||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) |
|||
.AddJwtBearer(options => |
|||
{ |
|||
options.Authority = "https://localhost:44301"; |
|||
options.Audience = "AbpAPIResource"; |
|||
|
|||
// See OpenIddictServerModule`s PreConfigureServices method.
|
|||
options.TokenValidationParameters.IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_C40DBB176E78")); |
|||
options.TokenValidationParameters.TokenDecryptionKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Abp_OpenIddict_Demo_87E33FC57D80")); |
|||
}); |
|||
|
|||
var app = builder.Build(); |
|||
|
|||
// Configure the HTTP request pipeline.
|
|||
if (app.Environment.IsDevelopment()) |
|||
{ |
|||
app.UseSwagger(); |
|||
app.UseSwaggerUI(); |
|||
} |
|||
|
|||
app.UseHttpsRedirection(); |
|||
|
|||
app.UseAuthentication(); |
|||
app.UseAuthorization(); |
|||
|
|||
app.MapControllers(); |
|||
|
|||
app.Run(); |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"profiles": { |
|||
"OpenIddict.Demo.API": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": true, |
|||
"launchBrowser": true, |
|||
"launchUrl": "swagger", |
|||
"applicationUrl": "https://localhost:44303", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information" |
|||
} |
|||
}, |
|||
"AllowedHosts": "*" |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
<CascadingAuthenticationState> |
|||
<Router AppAssembly="@typeof(App).Assembly"> |
|||
<Found Context="routeData"> |
|||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> |
|||
<NotAuthorized> |
|||
@if (context.User.Identity?.IsAuthenticated != true) |
|||
{ |
|||
<RedirectToLogin/> |
|||
} |
|||
else |
|||
{ |
|||
<p role="alert">You are not authorized to access this resource.</p> |
|||
} |
|||
</NotAuthorized> |
|||
</AuthorizeRouteView> |
|||
<FocusOnNavigate RouteData="@routeData" Selector="h1"/> |
|||
</Found> |
|||
<NotFound> |
|||
<PageTitle>Not found</PageTitle> |
|||
<LayoutView Layout="@typeof(MainLayout)"> |
|||
<p role="alert">Sorry, there's nothing at this address.</p> |
|||
</LayoutView> |
|||
</NotFound> |
|||
</Router> |
|||
</CascadingAuthenticationState> |
|||
@ -0,0 +1,16 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="IdentityModel" Version="6.0.0" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.3"/> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.3" PrivateAssets="all"/> |
|||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Authentication" Version="6.0.3"/> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,10 @@ |
|||
@page "/authentication/{action}" |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
<RemoteAuthenticatorView Action="@Action"/> |
|||
|
|||
@code{ |
|||
|
|||
[Parameter] |
|||
public string? Action { get; set; } |
|||
|
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
@page "/counter" |
|||
|
|||
<PageTitle>Counter</PageTitle> |
|||
|
|||
<h1>Counter</h1> |
|||
|
|||
<p role="status">Current count: @currentCount</p> |
|||
|
|||
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button> |
|||
|
|||
@code { |
|||
private int currentCount = 0; |
|||
|
|||
private void IncrementCount() |
|||
{ |
|||
currentCount++; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
@page "/fetchdata" |
|||
@inject HttpClient Http |
|||
|
|||
<PageTitle>Weather forecast</PageTitle> |
|||
|
|||
<h1>Weather forecast</h1> |
|||
|
|||
<p>This component demonstrates fetching data from the server.</p> |
|||
|
|||
@if (forecasts == null) |
|||
{ |
|||
<p> |
|||
<em>Loading...</em> |
|||
</p> |
|||
} |
|||
else |
|||
{ |
|||
<table class="table"> |
|||
<thead> |
|||
<tr> |
|||
<th>Date</th> |
|||
<th>Temp. (C)</th> |
|||
<th>Temp. (F)</th> |
|||
<th>Summary</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
@foreach (var forecast in forecasts) |
|||
{ |
|||
<tr> |
|||
<td>@forecast.Date.ToShortDateString()</td> |
|||
<td>@forecast.TemperatureC</td> |
|||
<td>@forecast.TemperatureF</td> |
|||
<td>@forecast.Summary</td> |
|||
</tr> |
|||
} |
|||
</tbody> |
|||
</table> |
|||
} |
|||
|
|||
@code { |
|||
private WeatherForecast[]? forecasts; |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/weather.json"); |
|||
} |
|||
|
|||
public class WeatherForecast |
|||
{ |
|||
public DateTime Date { get; set; } |
|||
|
|||
public int TemperatureC { get; set; } |
|||
|
|||
public string? Summary { get; set; } |
|||
|
|||
public int TemperatureF => 32 + (int) (TemperatureC / 0.5556); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,50 @@ |
|||
@page "/" |
|||
|
|||
@using System.Security.Claims |
|||
@inject AuthenticationStateProvider AuthenticationStateProvider |
|||
|
|||
<PageTitle>Index</PageTitle> |
|||
|
|||
<h1>Hello, world!</h1> |
|||
|
|||
<div class="alert alert-warning" role="alert"> |
|||
Before authentication will function correctly, you must configure your provider details in <code>Program.cs</code> |
|||
</div> |
|||
|
|||
Welcome to your new app. |
|||
|
|||
<SurveyPrompt Title="How is Blazor working for you?"/> |
|||
|
|||
@if (_claims.Count() > 0) |
|||
{ |
|||
<ul> |
|||
@foreach (var claim in _claims) |
|||
{ |
|||
<li>@claim.Type: @claim.Value</li> |
|||
} |
|||
</ul> |
|||
} |
|||
|
|||
|
|||
@code { |
|||
|
|||
protected override async Task OnInitializedAsync() |
|||
{ |
|||
await GetClaimsPrincipalData(); |
|||
await base.OnInitializedAsync(); |
|||
} |
|||
|
|||
private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>(); |
|||
|
|||
private async Task GetClaimsPrincipalData() |
|||
{ |
|||
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync(); |
|||
var user = authState.User; |
|||
|
|||
if (user.Identity.IsAuthenticated) |
|||
{ |
|||
|
|||
_claims = user.Claims; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,26 @@ |
|||
using IdentityModel; |
|||
using Microsoft.AspNetCore.Components.Web; |
|||
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; |
|||
using OpenIddict.Demo.Client.BlazorWASM; |
|||
|
|||
var builder = WebAssemblyHostBuilder.CreateDefault(args); |
|||
builder.RootComponents.Add<App>("#app"); |
|||
builder.RootComponents.Add<HeadOutlet>("head::after"); |
|||
|
|||
builder.Services.AddScoped(sp => new HttpClient {BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)}); |
|||
|
|||
builder.Services.AddOidcAuthentication(options => |
|||
{ |
|||
options.ProviderOptions.Authority = "https://localhost:44301/"; |
|||
options.ProviderOptions.ClientId = "AbpBlazorWASMApp"; |
|||
options.ProviderOptions.ResponseType = "code"; |
|||
|
|||
options.UserOptions.NameClaim = JwtClaimTypes.Name; |
|||
options.UserOptions.RoleClaim = JwtClaimTypes.Role; |
|||
|
|||
options.ProviderOptions.DefaultScopes.Add("roles"); |
|||
options.ProviderOptions.DefaultScopes.Add("email"); |
|||
options.ProviderOptions.DefaultScopes.Add("phone"); |
|||
}); |
|||
|
|||
await builder.Build().RunAsync(); |
|||
@ -0,0 +1,14 @@ |
|||
{ |
|||
"profiles": { |
|||
"OpenIddict.Demo.Client.BlazorWASM": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": true, |
|||
"launchBrowser": true, |
|||
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", |
|||
"applicationUrl": "https://localhost:44304", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
@using Microsoft.AspNetCore.Components.Authorization |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication |
|||
|
|||
@inject NavigationManager Navigation |
|||
@inject SignOutSessionStateManager SignOutManager |
|||
|
|||
<AuthorizeView> |
|||
<Authorized> |
|||
Hello, @context.User.Identity?.Name! |
|||
<button class="nav-link btn btn-link" @onclick="BeginSignOut">Log out</button> |
|||
</Authorized> |
|||
<NotAuthorized> |
|||
<a href="authentication/login">Log in</a> |
|||
</NotAuthorized> |
|||
</AuthorizeView> |
|||
|
|||
@code{ |
|||
|
|||
private async Task BeginSignOut(MouseEventArgs args) |
|||
{ |
|||
await SignOutManager.SetSignOutState(); |
|||
Navigation.NavigateTo("authentication/logout"); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
@inherits LayoutComponentBase |
|||
|
|||
<div class="page"> |
|||
<div class="sidebar"> |
|||
<NavMenu/> |
|||
</div> |
|||
|
|||
<main> |
|||
<div class="top-row px-4 auth"> |
|||
<LoginDisplay/> |
|||
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a> |
|||
</div> |
|||
|
|||
<article class="content px-4"> |
|||
@Body |
|||
</article> |
|||
</main> |
|||
</div> |
|||
@ -0,0 +1,81 @@ |
|||
.page { |
|||
position: relative; |
|||
display: flex; |
|||
flex-direction: column; |
|||
} |
|||
|
|||
main { |
|||
flex: 1; |
|||
} |
|||
|
|||
.sidebar { |
|||
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%); |
|||
} |
|||
|
|||
.top-row { |
|||
background-color: #f7f7f7; |
|||
border-bottom: 1px solid #d6d5d5; |
|||
justify-content: flex-end; |
|||
height: 3.5rem; |
|||
display: flex; |
|||
align-items: center; |
|||
} |
|||
|
|||
.top-row ::deep a, .top-row ::deep .btn-link { |
|||
white-space: nowrap; |
|||
margin-left: 1.5rem; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover { |
|||
text-decoration: underline; |
|||
} |
|||
|
|||
.top-row ::deep a:first-child { |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
} |
|||
|
|||
@media (max-width: 640.98px) { |
|||
.top-row:not(.auth) { |
|||
display: none; |
|||
} |
|||
|
|||
.top-row.auth { |
|||
justify-content: space-between; |
|||
} |
|||
|
|||
.top-row ::deep a, .top-row ::deep .btn-link { |
|||
margin-left: 0; |
|||
} |
|||
} |
|||
|
|||
@media (min-width: 641px) { |
|||
.page { |
|||
flex-direction: row; |
|||
} |
|||
|
|||
.sidebar { |
|||
width: 250px; |
|||
height: 100vh; |
|||
position: sticky; |
|||
top: 0; |
|||
} |
|||
|
|||
.top-row { |
|||
position: sticky; |
|||
top: 0; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.top-row.auth ::deep a:first-child { |
|||
flex: 1; |
|||
text-align: right; |
|||
width: 0; |
|||
} |
|||
|
|||
.top-row, article { |
|||
padding-left: 2rem !important; |
|||
padding-right: 1.5rem !important; |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
<div class="top-row ps-3 navbar navbar-dark"> |
|||
<div class="container-fluid"> |
|||
<a class="navbar-brand" href="">OpenIddict.Demo.Client.BlazorWASM</a> |
|||
<button title="Navigation menu" class="navbar-toggler" @onclick="ToggleNavMenu"> |
|||
<span class="navbar-toggler-icon"></span> |
|||
</button> |
|||
</div> |
|||
</div> |
|||
|
|||
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu"> |
|||
<nav class="flex-column"> |
|||
<div class="nav-item px-3"> |
|||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All"> |
|||
<span class="oi oi-home" aria-hidden="true"></span> Home |
|||
</NavLink> |
|||
</div> |
|||
<div class="nav-item px-3"> |
|||
<NavLink class="nav-link" href="counter"> |
|||
<span class="oi oi-plus" aria-hidden="true"></span> Counter |
|||
</NavLink> |
|||
</div> |
|||
<div class="nav-item px-3"> |
|||
<NavLink class="nav-link" href="fetchdata"> |
|||
<span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data |
|||
</NavLink> |
|||
</div> |
|||
</nav> |
|||
</div> |
|||
|
|||
@code { |
|||
private bool collapseNavMenu = true; |
|||
|
|||
private string? NavMenuCssClass => collapseNavMenu ? "collapse" : null; |
|||
|
|||
private void ToggleNavMenu() |
|||
{ |
|||
collapseNavMenu = !collapseNavMenu; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
.navbar-toggler { |
|||
background-color: rgba(255, 255, 255, 0.1); |
|||
} |
|||
|
|||
.top-row { |
|||
height: 3.5rem; |
|||
background-color: rgba(0,0,0,0.4); |
|||
} |
|||
|
|||
.navbar-brand { |
|||
font-size: 1.1rem; |
|||
} |
|||
|
|||
.oi { |
|||
width: 2rem; |
|||
font-size: 1.1rem; |
|||
vertical-align: text-top; |
|||
top: -2px; |
|||
} |
|||
|
|||
.nav-item { |
|||
font-size: 0.9rem; |
|||
padding-bottom: 0.5rem; |
|||
} |
|||
|
|||
.nav-item:first-of-type { |
|||
padding-top: 1rem; |
|||
} |
|||
|
|||
.nav-item:last-of-type { |
|||
padding-bottom: 1rem; |
|||
} |
|||
|
|||
.nav-item ::deep a { |
|||
color: #d7d7d7; |
|||
border-radius: 4px; |
|||
height: 3rem; |
|||
display: flex; |
|||
align-items: center; |
|||
line-height: 3rem; |
|||
} |
|||
|
|||
.nav-item ::deep a.active { |
|||
background-color: rgba(255,255,255,0.25); |
|||
color: white; |
|||
} |
|||
|
|||
.nav-item ::deep a:hover { |
|||
background-color: rgba(255,255,255,0.1); |
|||
color: white; |
|||
} |
|||
|
|||
@media (min-width: 641px) { |
|||
.navbar-toggler { |
|||
display: none; |
|||
} |
|||
|
|||
.collapse { |
|||
/* Never collapse the sidebar for wide screens */ |
|||
display: block; |
|||
} |
|||
} |
|||
@ -0,0 +1,10 @@ |
|||
@inject NavigationManager Navigation |
|||
|
|||
@code { |
|||
|
|||
protected override void OnInitialized() |
|||
{ |
|||
Navigation.NavigateTo($"authentication/login?returnUrl={Uri.EscapeDataString(Navigation.Uri)}"); |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
<div class="alert alert-secondary mt-4"> |
|||
<span class="oi oi-pencil me-2" aria-hidden="true"></span> |
|||
<strong>@Title</strong> |
|||
|
|||
<span class="text-nowrap"> |
|||
Please take our |
|||
<a target="_blank" class="font-weight-bold link-dark" href="https://go.microsoft.com/fwlink/?linkid=2148851">brief survey</a> |
|||
</span> |
|||
and tell us what you think. |
|||
</div> |
|||
|
|||
@code { |
|||
// Demonstrates how a parent component can supply parameters |
|||
[Parameter] |
|||
public string? Title { get; set; } |
|||
|
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
@using System.Net.Http |
|||
@using System.Net.Http.Json |
|||
@using Microsoft.AspNetCore.Components.Authorization |
|||
@using Microsoft.AspNetCore.Components.Forms |
|||
@using Microsoft.AspNetCore.Components.Routing |
|||
@using Microsoft.AspNetCore.Components.Web |
|||
@using Microsoft.AspNetCore.Components.Web.Virtualization |
|||
@using Microsoft.AspNetCore.Components.WebAssembly.Http |
|||
@using Microsoft.JSInterop |
|||
@using OpenIddict.Demo.Client.BlazorWASM |
|||
@using OpenIddict.Demo.Client.BlazorWASM.Shared |
|||
@ -0,0 +1,6 @@ |
|||
{ |
|||
"Local": { |
|||
"Authority": "https://login.microsoftonline.com/", |
|||
"ClientId": "33333333-3333-3333-33333333333333333" |
|||
} |
|||
} |
|||
@ -0,0 +1,3 @@ |
|||
{ |
|||
|
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); |
|||
|
|||
html, body { |
|||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; |
|||
} |
|||
|
|||
h1:focus { |
|||
outline: none; |
|||
} |
|||
|
|||
a, .btn-link { |
|||
color: #0071c1; |
|||
} |
|||
|
|||
.btn-primary { |
|||
color: #fff; |
|||
background-color: #1b6ec2; |
|||
border-color: #1861ac; |
|||
} |
|||
|
|||
.content { |
|||
padding-top: 1.1rem; |
|||
} |
|||
|
|||
.valid.modified:not([type=checkbox]) { |
|||
outline: 1px solid #26b050; |
|||
} |
|||
|
|||
.invalid { |
|||
outline: 1px solid red; |
|||
} |
|||
|
|||
.validation-message { |
|||
color: red; |
|||
} |
|||
|
|||
#blazor-error-ui { |
|||
background: lightyellow; |
|||
bottom: 0; |
|||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); |
|||
display: none; |
|||
left: 0; |
|||
padding: 0.6rem 1.25rem 0.7rem 1.25rem; |
|||
position: fixed; |
|||
width: 100%; |
|||
z-index: 1000; |
|||
} |
|||
|
|||
#blazor-error-ui .dismiss { |
|||
cursor: pointer; |
|||
position: absolute; |
|||
right: 0.75rem; |
|||
top: 0.5rem; |
|||
} |
|||
|
|||
.blazor-error-boundary { |
|||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; |
|||
padding: 1rem 1rem 1rem 3.7rem; |
|||
color: white; |
|||
} |
|||
|
|||
.blazor-error-boundary::after { |
|||
content: "An error has occurred." |
|||
} |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,86 @@ |
|||
SIL OPEN FONT LICENSE Version 1.1 |
|||
|
|||
Copyright (c) 2014 Waybury |
|||
|
|||
PREAMBLE |
|||
The goals of the Open Font License (OFL) are to stimulate worldwide |
|||
development of collaborative font projects, to support the font creation |
|||
efforts of academic and linguistic communities, and to provide a free and |
|||
open framework in which fonts may be shared and improved in partnership |
|||
with others. |
|||
|
|||
The OFL allows the licensed fonts to be used, studied, modified and |
|||
redistributed freely as long as they are not sold by themselves. The |
|||
fonts, including any derivative works, can be bundled, embedded, |
|||
redistributed and/or sold with any software provided that any reserved |
|||
names are not used by derivative works. The fonts and derivatives, |
|||
however, cannot be released under any other type of license. The |
|||
requirement for fonts to remain under this license does not apply |
|||
to any document created using the fonts or their derivatives. |
|||
|
|||
DEFINITIONS |
|||
"Font Software" refers to the set of files released by the Copyright |
|||
Holder(s) under this license and clearly marked as such. This may |
|||
include source files, build scripts and documentation. |
|||
|
|||
"Reserved Font Name" refers to any names specified as such after the |
|||
copyright statement(s). |
|||
|
|||
"Original Version" refers to the collection of Font Software components as |
|||
distributed by the Copyright Holder(s). |
|||
|
|||
"Modified Version" refers to any derivative made by adding to, deleting, |
|||
or substituting -- in part or in whole -- any of the components of the |
|||
Original Version, by changing formats or by porting the Font Software to a |
|||
new environment. |
|||
|
|||
"Author" refers to any designer, engineer, programmer, technical |
|||
writer or other person who contributed to the Font Software. |
|||
|
|||
PERMISSION & CONDITIONS |
|||
Permission is hereby granted, free of charge, to any person obtaining |
|||
a copy of the Font Software, to use, study, copy, merge, embed, modify, |
|||
redistribute, and sell modified and unmodified copies of the Font |
|||
Software, subject to the following conditions: |
|||
|
|||
1) Neither the Font Software nor any of its individual components, |
|||
in Original or Modified Versions, may be sold by itself. |
|||
|
|||
2) Original or Modified Versions of the Font Software may be bundled, |
|||
redistributed and/or sold with any software, provided that each copy |
|||
contains the above copyright notice and this license. These can be |
|||
included either as stand-alone text files, human-readable headers or |
|||
in the appropriate machine-readable metadata fields within text or |
|||
binary files as long as those fields can be easily viewed by the user. |
|||
|
|||
3) No Modified Version of the Font Software may use the Reserved Font |
|||
Name(s) unless explicit written permission is granted by the corresponding |
|||
Copyright Holder. This restriction only applies to the primary font name as |
|||
presented to the users. |
|||
|
|||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font |
|||
Software shall not be used to promote, endorse or advertise any |
|||
Modified Version, except to acknowledge the contribution(s) of the |
|||
Copyright Holder(s) and the Author(s) or with their explicit written |
|||
permission. |
|||
|
|||
5) The Font Software, modified or unmodified, in part or in whole, |
|||
must be distributed entirely under this license, and must not be |
|||
distributed under any other license. The requirement for fonts to |
|||
remain under this license does not apply to any document created |
|||
using the Font Software. |
|||
|
|||
TERMINATION |
|||
This license becomes null and void if any of the above conditions are |
|||
not met. |
|||
|
|||
DISCLAIMER |
|||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF |
|||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT |
|||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE |
|||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
|||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL |
|||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
|||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM |
|||
OTHER DEALINGS IN THE FONT SOFTWARE. |
|||
@ -0,0 +1,21 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2014 Waybury |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
THE SOFTWARE. |
|||
@ -0,0 +1,114 @@ |
|||
[Open Iconic v1.1.1](http://useiconic.com/open) |
|||
=========== |
|||
|
|||
### Open Iconic is the open source sibling of [Iconic](http://useiconic.com). It is a hyper-legible collection of 223 icons with a tiny footprint—ready to use with Bootstrap and Foundation. [View the collection](http://useiconic.com/open#icons) |
|||
|
|||
|
|||
|
|||
## What's in Open Iconic? |
|||
|
|||
* 223 icons designed to be legible down to 8 pixels |
|||
* Super-light SVG files - 61.8 for the entire set |
|||
* SVG sprite—the modern replacement for icon fonts |
|||
* Webfont (EOT, OTF, SVG, TTF, WOFF), PNG and WebP formats |
|||
* Webfont stylesheets (including versions for Bootstrap and Foundation) in CSS, LESS, SCSS and Stylus formats |
|||
* PNG and WebP raster images in 8px, 16px, 24px, 32px, 48px and 64px. |
|||
|
|||
|
|||
## Getting Started |
|||
|
|||
#### For code samples and everything else you need to get started with Open Iconic, check out our [Icons](http://useiconic.com/open#icons) and [Reference](http://useiconic.com/open#reference) sections. |
|||
|
|||
### General Usage |
|||
|
|||
#### Using Open Iconic's SVGs |
|||
|
|||
We like SVGs and we think they're the way to display icons on the web. Since Open Iconic are just basic SVGs, we suggest you display them like you would any other image (don't forget the `alt` attribute). |
|||
|
|||
``` |
|||
<img src="/open-iconic/svg/icon-name.svg" alt="icon name"> |
|||
``` |
|||
|
|||
#### Using Open Iconic's SVG Sprite |
|||
|
|||
Open Iconic also comes in a SVG sprite which allows you to display all the icons in the set with a single request. It's like an icon font, without being a hack. |
|||
|
|||
Adding an icon from an SVG sprite is a little different than what you're used to, but it's still a piece of cake. *Tip: To make your icons easily style able, we suggest adding a general class to the* `<svg>` *tag and a unique class name for each different icon in the* `<use>` *tag.* |
|||
|
|||
``` |
|||
<svg class="icon"> |
|||
<use xlink:href="open-iconic.svg#account-login" class="icon-account-login"></use> |
|||
</svg> |
|||
``` |
|||
|
|||
Sizing icons only needs basic CSS. All the icons are in a square format, so just set the `<svg>` tag with equal width and height dimensions. |
|||
|
|||
``` |
|||
.icon { |
|||
width: 16px; |
|||
height: 16px; |
|||
} |
|||
``` |
|||
|
|||
Coloring icons is even easier. All you need to do is set the `fill` rule on the `<use>` tag. |
|||
|
|||
``` |
|||
.icon-account-login { |
|||
fill: #f00; |
|||
} |
|||
``` |
|||
|
|||
To learn more about SVG Sprites, read [Chris Coyier's guide](http://css-tricks.com/svg-sprites-use-better-icon-fonts/). |
|||
|
|||
#### Using Open Iconic's Icon Font... |
|||
|
|||
|
|||
##### …with Bootstrap |
|||
|
|||
You can find our Bootstrap stylesheets in `font/css/open-iconic-bootstrap.{css, less, scss, styl}` |
|||
|
|||
|
|||
``` |
|||
<link href="/open-iconic/font/css/open-iconic-bootstrap.css" rel="stylesheet"> |
|||
``` |
|||
|
|||
|
|||
``` |
|||
<span class="oi oi-icon-name" title="icon name" aria-hidden="true"></span> |
|||
``` |
|||
|
|||
##### …with Foundation |
|||
|
|||
You can find our Foundation stylesheets in `font/css/open-iconic-foundation.{css, less, scss, styl}` |
|||
|
|||
``` |
|||
<link href="/open-iconic/font/css/open-iconic-foundation.css" rel="stylesheet"> |
|||
``` |
|||
|
|||
|
|||
``` |
|||
<span class="fi-icon-name" title="icon name" aria-hidden="true"></span> |
|||
``` |
|||
|
|||
##### …on its own |
|||
|
|||
You can find our default stylesheets in `font/css/open-iconic.{css, less, scss, styl}` |
|||
|
|||
``` |
|||
<link href="/open-iconic/font/css/open-iconic.css" rel="stylesheet"> |
|||
``` |
|||
|
|||
``` |
|||
<span class="oi" data-glyph="icon-name" title="icon name" aria-hidden="true"></span> |
|||
``` |
|||
|
|||
|
|||
## License |
|||
|
|||
### Icons |
|||
|
|||
All code (including SVG markup) is under the [MIT License](http://opensource.org/licenses/MIT). |
|||
|
|||
### Fonts |
|||
|
|||
All fonts are under the [SIL Licensed](http://scripts.sil.org/cms/scripts/page.php?item_id=OFL_web). |
|||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 54 KiB |
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
@ -0,0 +1,26 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
|
|||
<head> |
|||
<meta charset="utf-8" /> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> |
|||
<title>OpenIddict.Demo.Client.BlazorWASM</title> |
|||
<base href="/" /> |
|||
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" /> |
|||
<link href="css/app.css" rel="stylesheet" /> |
|||
<link href="OpenIddict.Demo.Client.BlazorWASM.styles.css" rel="stylesheet" /> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app">Loading...</div> |
|||
|
|||
<div id="blazor-error-ui"> |
|||
An unhandled error has occurred. |
|||
<a href="" class="reload">Reload</a> |
|||
<a class="dismiss">🗙</a> |
|||
</div> |
|||
<script src="_content/Microsoft.AspNetCore.Components.WebAssembly.Authentication/AuthenticationService.js"></script> |
|||
<script src="_framework/blazor.webassembly.js"></script> |
|||
</body> |
|||
|
|||
</html> |
|||
@ -0,0 +1,27 @@ |
|||
[ |
|||
{ |
|||
"date": "2018-05-06", |
|||
"temperatureC": 1, |
|||
"summary": "Freezing" |
|||
}, |
|||
{ |
|||
"date": "2018-05-07", |
|||
"temperatureC": 14, |
|||
"summary": "Bracing" |
|||
}, |
|||
{ |
|||
"date": "2018-05-08", |
|||
"temperatureC": -13, |
|||
"summary": "Freezing" |
|||
}, |
|||
{ |
|||
"date": "2018-05-09", |
|||
"temperatureC": -16, |
|||
"summary": "Balmy" |
|||
}, |
|||
{ |
|||
"date": "2018-05-10", |
|||
"temperatureC": -2, |
|||
"summary": "Chilly" |
|||
} |
|||
] |
|||
@ -0,0 +1,15 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<PropertyGroup> |
|||
<OutputType>Exe</OutputType> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
<Nullable>enable</Nullable> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="IdentityModel" Version="6.0.0" /> |
|||
<ProjectReference Include="..\..\..\..\framework\src\Volo.Abp.AspNetCore.Mvc.Contracts\Volo.Abp.AspNetCore.Mvc.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,149 @@ |
|||
using System.Net.Http.Headers; |
|||
using System.Text.Json; |
|||
using IdentityModel.Client; |
|||
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations; |
|||
|
|||
const string email = "admin@abp.io"; |
|||
const string password = "1q2w3E*"; |
|||
const string server = "https://localhost:44301/"; |
|||
const string serverApi = "https://localhost:44301/api/abp/application-configuration"; |
|||
const string api = "https://localhost:44303/api/claims"; |
|||
const string clientId = "AbpApp"; |
|||
const string clientSecret = "1q2w3e*"; |
|||
|
|||
var client = new HttpClient(); |
|||
|
|||
var configuration = await client.GetDiscoveryDocumentAsync(server); |
|||
if (configuration.IsError) |
|||
{ |
|||
throw new Exception(configuration.Error); |
|||
} |
|||
|
|||
var passwordTokenRequest = new PasswordTokenRequest |
|||
{ |
|||
Address = configuration.TokenEndpoint, |
|||
ClientId = clientId, |
|||
ClientSecret = clientSecret, |
|||
UserName = email, |
|||
Password = password, |
|||
Scope = "AbpAPI profile roles email phone offline_access", |
|||
}; |
|||
passwordTokenRequest.Headers.Add("__tenant", "Default"); |
|||
var tokenResponse = await client.RequestPasswordTokenAsync(passwordTokenRequest); |
|||
|
|||
if (tokenResponse.IsError) |
|||
{ |
|||
throw new Exception(tokenResponse.Error); |
|||
} |
|||
|
|||
Console.WriteLine("Access token: {0}", tokenResponse.AccessToken); |
|||
Console.WriteLine(); |
|||
Console.WriteLine("Refresh token: {0}", tokenResponse.RefreshToken); |
|||
Console.WriteLine(); |
|||
|
|||
var refreshTokenResponse = await client.RequestRefreshTokenAsync(new RefreshTokenRequest() |
|||
{ |
|||
Address = configuration.TokenEndpoint, |
|||
ClientId = clientId, |
|||
ClientSecret = clientSecret, |
|||
RefreshToken = tokenResponse.RefreshToken |
|||
}); |
|||
|
|||
if (refreshTokenResponse.IsError) |
|||
{ |
|||
throw new Exception(refreshTokenResponse.Error); |
|||
} |
|||
|
|||
Console.WriteLine("New Access token: {0}", refreshTokenResponse.AccessToken); |
|||
Console.WriteLine(); |
|||
Console.WriteLine("New Refresh token: {0}", refreshTokenResponse.RefreshToken); |
|||
Console.WriteLine(); |
|||
|
|||
var userinfo = await client.GetUserInfoAsync(new UserInfoRequest() |
|||
{ |
|||
Address = configuration.UserInfoEndpoint, |
|||
Token = tokenResponse.AccessToken |
|||
}); |
|||
if (userinfo.IsError) |
|||
{ |
|||
throw new Exception(userinfo.Error); |
|||
} |
|||
|
|||
Console.WriteLine("UserInfo: {0}", JsonSerializer.Serialize(JsonDocument.Parse(userinfo.Raw), new JsonSerializerOptions |
|||
{ |
|||
WriteIndented = true |
|||
})); |
|||
Console.WriteLine(); |
|||
|
|||
|
|||
var introspectionResponse = await client.IntrospectTokenAsync(new TokenIntrospectionRequest() |
|||
{ |
|||
Address = configuration.IntrospectionEndpoint, |
|||
ClientId = clientId, |
|||
ClientSecret = clientSecret, |
|||
Token = tokenResponse.AccessToken, |
|||
TokenTypeHint = "access_token" |
|||
}); |
|||
if (introspectionResponse.IsError) |
|||
{ |
|||
throw new Exception(introspectionResponse.Error); |
|||
} |
|||
|
|||
Console.WriteLine("Introspection : {0}", JsonSerializer.Serialize(JsonDocument.Parse(introspectionResponse.Raw), new JsonSerializerOptions |
|||
{ |
|||
WriteIndented = true |
|||
})); |
|||
Console.WriteLine(); |
|||
|
|||
var serverRequest = new HttpRequestMessage(HttpMethod.Get, serverApi); |
|||
serverRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResponse.AccessToken); |
|||
|
|||
var serverResponse = await client.SendAsync(serverRequest); |
|||
serverResponse.EnsureSuccessStatusCode(); |
|||
|
|||
var dto = JsonSerializer.Deserialize<ApplicationConfigurationDto>(await serverResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions() |
|||
{ |
|||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase |
|||
}); |
|||
Console.WriteLine("Server API response: {0}", JsonSerializer.Serialize(dto.CurrentUser, new JsonSerializerOptions |
|||
{ |
|||
WriteIndented = true |
|||
})); |
|||
|
|||
Console.WriteLine(); |
|||
|
|||
var request = new HttpRequestMessage(HttpMethod.Get, api); |
|||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", tokenResponse.AccessToken); |
|||
|
|||
var response = await client.SendAsync(request); |
|||
response.EnsureSuccessStatusCode(); |
|||
|
|||
Console.WriteLine("API response: {0}", JsonSerializer.Serialize(JsonDocument.Parse(await response.Content.ReadAsStringAsync()), new JsonSerializerOptions |
|||
{ |
|||
WriteIndented = true |
|||
})); |
|||
|
|||
Console.WriteLine(); |
|||
|
|||
client = new HttpClient(); |
|||
|
|||
tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest |
|||
{ |
|||
Address = configuration.TokenEndpoint, |
|||
|
|||
ClientId = clientId, |
|||
ClientSecret = clientSecret, |
|||
|
|||
Scope = "AbpAPI profile roles email phone offline_access", |
|||
}); |
|||
|
|||
if (tokenResponse.IsError) |
|||
{ |
|||
Console.WriteLine(tokenResponse.Error); |
|||
return; |
|||
} |
|||
|
|||
Console.WriteLine("Access token: {0}", tokenResponse.AccessToken); |
|||
Console.WriteLine(); |
|||
Console.WriteLine("Refresh token: {0}", tokenResponse.RefreshToken); |
|||
Console.WriteLine(); |
|||
@ -0,0 +1,14 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk.Web"> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<Nullable>enable</Nullable> |
|||
<ImplicitUsings>enable</ImplicitUsings> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="IdentityModel" Version="6.0.0" /> |
|||
<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.3" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,26 @@ |
|||
@page |
|||
@model ErrorModel |
|||
@{ |
|||
ViewData["Title"] = "Error"; |
|||
} |
|||
|
|||
<h1 class="text-danger">Error.</h1> |
|||
<h2 class="text-danger">An error occurred while processing your request.</h2> |
|||
|
|||
@if (Model.ShowRequestId) |
|||
{ |
|||
<p> |
|||
<strong>Request ID:</strong> <code>@Model.RequestId</code> |
|||
</p> |
|||
} |
|||
|
|||
<h3>Development Mode</h3> |
|||
<p> |
|||
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred. |
|||
</p> |
|||
<p> |
|||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong> |
|||
It can result in displaying sensitive information from exceptions to end users. |
|||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong> |
|||
and restarting the app. |
|||
</p> |
|||
@ -0,0 +1,26 @@ |
|||
using System.Diagnostics; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
|
|||
namespace OpenIddict.Demo.Client.Pages; |
|||
|
|||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] |
|||
[IgnoreAntiforgeryToken] |
|||
public class ErrorModel : PageModel |
|||
{ |
|||
public string? RequestId { get; set; } |
|||
|
|||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); |
|||
|
|||
private readonly ILogger<ErrorModel> _logger; |
|||
|
|||
public ErrorModel(ILogger<ErrorModel> logger) |
|||
{ |
|||
_logger = logger; |
|||
} |
|||
|
|||
public void OnGet() |
|||
{ |
|||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; |
|||
} |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
@page |
|||
@using Microsoft.AspNetCore.Authentication |
|||
@model IndexModel |
|||
@{ |
|||
ViewData["Title"] = "Home page"; |
|||
} |
|||
|
|||
<div class="text-center"> |
|||
<h1 class="display-4">Welcome</h1> |
|||
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> |
|||
|
|||
<a class="btn btn-primary" href="/Login">Login</a> |
|||
<a class="btn btn-warning" href="/Logout">Loout</a> |
|||
|
|||
@if (HttpContext.User.Identity != null && HttpContext.User.Identity.IsAuthenticated) |
|||
{ |
|||
<ul class="list-group mt-3 text-start"> |
|||
@foreach (var claim in HttpContext.User.Claims) |
|||
{ |
|||
<li class="list-group-item">@claim.Type : @claim.Value</li> |
|||
} |
|||
</ul> |
|||
|
|||
<p>HttpContext.GetTokenAsync("access_token") |
|||
<br/> |
|||
@await HttpContext.GetTokenAsync("access_token") |
|||
</p> |
|||
} |
|||
</div> |
|||
@ -0,0 +1,17 @@ |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
|
|||
namespace OpenIddict.Demo.Client.Pages; |
|||
|
|||
public class IndexModel : PageModel |
|||
{ |
|||
private readonly ILogger<IndexModel> _logger; |
|||
|
|||
public IndexModel(ILogger<IndexModel> logger) |
|||
{ |
|||
_logger = logger; |
|||
} |
|||
|
|||
public void OnGet() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
@page |
|||
@model OpenIddict.Demo.Client.Pages.Login |
|||
|
|||
@{ |
|||
ViewData["Title"] = "Login page"; |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
using Microsoft.AspNetCore.Authentication; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
|
|||
namespace OpenIddict.Demo.Client.Pages; |
|||
|
|||
public class Login : PageModel |
|||
{ |
|||
public IActionResult OnGet() |
|||
{ |
|||
return Challenge(new AuthenticationProperties { RedirectUri = "/" }, "oidc"); |
|||
} |
|||
} |
|||
@ -0,0 +1,6 @@ |
|||
@page |
|||
@model OpenIddict.Demo.Client.Pages.Logout |
|||
|
|||
@{ |
|||
ViewData["Title"] = "Logout page"; |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.AspNetCore.Mvc.RazorPages; |
|||
|
|||
namespace OpenIddict.Demo.Client.Pages; |
|||
|
|||
public class Logout : PageModel |
|||
{ |
|||
public IActionResult OnGet() |
|||
{ |
|||
return SignOut("Cookies", "oidc"); |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
<!DOCTYPE html> |
|||
<html lang="en"> |
|||
<head> |
|||
<meta charset="utf-8"/> |
|||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
|||
<title>@ViewData["Title"] - OpenIddict.Demo.Client</title> |
|||
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css"/> |
|||
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true"/> |
|||
<link rel="stylesheet" href="~/OpenIddict.Demo.Client.styles.css" asp-append-version="true"/> |
|||
</head> |
|||
<body> |
|||
<header> |
|||
<nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"> |
|||
<div class="container"> |
|||
<a class="navbar-brand" asp-area="" asp-page="/Index">OpenIddict.Demo.Client</a> |
|||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent" |
|||
aria-expanded="false" aria-label="Toggle navigation"> |
|||
<span class="navbar-toggler-icon"></span> |
|||
</button> |
|||
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between"> |
|||
<ul class="navbar-nav flex-grow-1"> |
|||
<li class="nav-item"> |
|||
<a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a> |
|||
</li> |
|||
<li class="nav-item"> |
|||
<a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a> |
|||
</li> |
|||
</ul> |
|||
</div> |
|||
</div> |
|||
</nav> |
|||
</header> |
|||
<div class="container"> |
|||
<main role="main" class="pb-3"> |
|||
@RenderBody() |
|||
</main> |
|||
</div> |
|||
|
|||
<footer class="border-top footer text-muted"> |
|||
<div class="container"> |
|||
© 2022 - OpenIddict.Demo.Client - <a asp-area="" asp-page="/Privacy">Privacy</a> |
|||
</div> |
|||
</footer> |
|||
|
|||
<script src="~/lib/jquery/dist/jquery.min.js"></script> |
|||
<script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script> |
|||
<script src="~/js/site.js" asp-append-version="true"></script> |
|||
|
|||
@await RenderSectionAsync("Scripts", required: false) |
|||
</body> |
|||
</html> |
|||
@ -0,0 +1,48 @@ |
|||
/* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification |
|||
for details on configuring this project to bundle and minify static web assets. */ |
|||
|
|||
a.navbar-brand { |
|||
white-space: normal; |
|||
text-align: center; |
|||
word-break: break-all; |
|||
} |
|||
|
|||
a { |
|||
color: #0077cc; |
|||
} |
|||
|
|||
.btn-primary { |
|||
color: #fff; |
|||
background-color: #1b6ec2; |
|||
border-color: #1861ac; |
|||
} |
|||
|
|||
.nav-pills .nav-link.active, .nav-pills .show > .nav-link { |
|||
color: #fff; |
|||
background-color: #1b6ec2; |
|||
border-color: #1861ac; |
|||
} |
|||
|
|||
.border-top { |
|||
border-top: 1px solid #e5e5e5; |
|||
} |
|||
.border-bottom { |
|||
border-bottom: 1px solid #e5e5e5; |
|||
} |
|||
|
|||
.box-shadow { |
|||
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); |
|||
} |
|||
|
|||
button.accept-policy { |
|||
font-size: 1rem; |
|||
line-height: inherit; |
|||
} |
|||
|
|||
.footer { |
|||
position: absolute; |
|||
bottom: 0; |
|||
width: 100%; |
|||
white-space: nowrap; |
|||
line-height: 60px; |
|||
} |
|||
@ -0,0 +1,2 @@ |
|||
<script src="~/lib/jquery-validation/dist/jquery.validate.min.js"></script> |
|||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script> |
|||
@ -0,0 +1,3 @@ |
|||
@using OpenIddict.Demo.Client |
|||
@namespace OpenIddict.Demo.Client.Pages |
|||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
|||
@ -0,0 +1,3 @@ |
|||
@{ |
|||
Layout = "_Layout"; |
|||
} |
|||
@ -0,0 +1,60 @@ |
|||
using IdentityModel; |
|||
|
|||
var builder = WebApplication.CreateBuilder(args); |
|||
builder.Logging.ClearProviders(); |
|||
builder.Logging.AddConsole(); |
|||
|
|||
// Add services to the container.
|
|||
builder.Services.AddRazorPages(); |
|||
|
|||
builder.Services.AddAuthentication(options => |
|||
{ |
|||
options.DefaultScheme = "Cookies"; |
|||
options.DefaultChallengeScheme = "oidc"; |
|||
}) |
|||
.AddCookie("Cookies", options => |
|||
{ |
|||
options.ExpireTimeSpan = TimeSpan.FromDays(365); |
|||
}) |
|||
.AddOpenIdConnect("oidc", options => |
|||
{ |
|||
options.Authority = "https://localhost:44301/"; |
|||
|
|||
options.ClientId = "AbpApp"; |
|||
options.ClientSecret = "1q2w3e*"; |
|||
|
|||
options.RequireHttpsMetadata = true; |
|||
options.GetClaimsFromUserInfoEndpoint = true; |
|||
options.SaveTokens = true; |
|||
|
|||
options.UsePkce = true; |
|||
|
|||
options.ResponseType = OidcConstants.ResponseTypes.Code; |
|||
|
|||
options.SignOutScheme = "Cookies"; |
|||
|
|||
options.Scope.Add("email"); |
|||
options.Scope.Add("roles"); |
|||
}); |
|||
|
|||
var app = builder.Build(); |
|||
|
|||
// Configure the HTTP request pipeline.
|
|||
if (!app.Environment.IsDevelopment()) |
|||
{ |
|||
app.UseExceptionHandler("/Error"); |
|||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
|||
app.UseHsts(); |
|||
} |
|||
|
|||
app.UseHttpsRedirection(); |
|||
app.UseStaticFiles(); |
|||
|
|||
app.UseRouting(); |
|||
|
|||
app.UseAuthentication(); |
|||
app.UseAuthorization(); |
|||
|
|||
app.MapRazorPages(); |
|||
|
|||
app.Run(); |
|||
@ -0,0 +1,13 @@ |
|||
{ |
|||
"profiles": { |
|||
"OpenIddict.Demo.Client.Mvc": { |
|||
"commandName": "Project", |
|||
"dotnetRunMessages": true, |
|||
"launchBrowser": true, |
|||
"applicationUrl": "https://localhost:44302", |
|||
"environmentVariables": { |
|||
"ASPNETCORE_ENVIRONMENT": "Development" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
{ |
|||
"Logging": { |
|||
"LogLevel": { |
|||
"Default": "Information" |
|||
} |
|||
}, |
|||
"AllowedHosts": "*" |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
html { |
|||
font-size: 14px; |
|||
} |
|||
|
|||
@media (min-width: 768px) { |
|||
html { |
|||
font-size: 16px; |
|||
} |
|||
} |
|||
|
|||
html { |
|||
position: relative; |
|||
min-height: 100%; |
|||
} |
|||
|
|||
body { |
|||
margin-bottom: 60px; |
|||
} |
|||
|
After Width: | Height: | Size: 5.3 KiB |
@ -0,0 +1,4 @@ |
|||
// Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification
|
|||
// for details on configuring this project to bundle and minify static web assets.
|
|||
|
|||
// Write your JavaScript code.
|
|||
@ -0,0 +1,22 @@ |
|||
The MIT License (MIT) |
|||
|
|||
Copyright (c) 2011-2021 Twitter, Inc. |
|||
Copyright (c) 2011-2021 The Bootstrap Authors |
|||
|
|||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|||
of this software and associated documentation files (the "Software"), to deal |
|||
in the Software without restriction, including without limitation the rights |
|||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|||
copies of the Software, and to permit persons to whom the Software is |
|||
furnished to do so, subject to the following conditions: |
|||
|
|||
The above copyright notice and this permission notice shall be included in |
|||
all copies or substantial portions of the Software. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
|||
THE SOFTWARE. |
|||
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1,427 @@ |
|||
/*! |
|||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/) |
|||
* Copyright 2011-2021 The Bootstrap Authors |
|||
* Copyright 2011-2021 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
|||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
|||
*/ |
|||
*, |
|||
*::before, |
|||
*::after { |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
@media (prefers-reduced-motion: no-preference) { |
|||
:root { |
|||
scroll-behavior: smooth; |
|||
} |
|||
} |
|||
|
|||
body { |
|||
margin: 0; |
|||
font-family: var(--bs-body-font-family); |
|||
font-size: var(--bs-body-font-size); |
|||
font-weight: var(--bs-body-font-weight); |
|||
line-height: var(--bs-body-line-height); |
|||
color: var(--bs-body-color); |
|||
text-align: var(--bs-body-text-align); |
|||
background-color: var(--bs-body-bg); |
|||
-webkit-text-size-adjust: 100%; |
|||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
|||
} |
|||
|
|||
hr { |
|||
margin: 1rem 0; |
|||
color: inherit; |
|||
background-color: currentColor; |
|||
border: 0; |
|||
opacity: 0.25; |
|||
} |
|||
|
|||
hr:not([size]) { |
|||
height: 1px; |
|||
} |
|||
|
|||
h6, h5, h4, h3, h2, h1 { |
|||
margin-top: 0; |
|||
margin-bottom: 0.5rem; |
|||
font-weight: 500; |
|||
line-height: 1.2; |
|||
} |
|||
|
|||
h1 { |
|||
font-size: calc(1.375rem + 1.5vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h1 { |
|||
font-size: 2.5rem; |
|||
} |
|||
} |
|||
|
|||
h2 { |
|||
font-size: calc(1.325rem + 0.9vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h2 { |
|||
font-size: 2rem; |
|||
} |
|||
} |
|||
|
|||
h3 { |
|||
font-size: calc(1.3rem + 0.6vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h3 { |
|||
font-size: 1.75rem; |
|||
} |
|||
} |
|||
|
|||
h4 { |
|||
font-size: calc(1.275rem + 0.3vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h4 { |
|||
font-size: 1.5rem; |
|||
} |
|||
} |
|||
|
|||
h5 { |
|||
font-size: 1.25rem; |
|||
} |
|||
|
|||
h6 { |
|||
font-size: 1rem; |
|||
} |
|||
|
|||
p { |
|||
margin-top: 0; |
|||
margin-bottom: 1rem; |
|||
} |
|||
|
|||
abbr[title], |
|||
abbr[data-bs-original-title] { |
|||
-webkit-text-decoration: underline dotted; |
|||
text-decoration: underline dotted; |
|||
cursor: help; |
|||
-webkit-text-decoration-skip-ink: none; |
|||
text-decoration-skip-ink: none; |
|||
} |
|||
|
|||
address { |
|||
margin-bottom: 1rem; |
|||
font-style: normal; |
|||
line-height: inherit; |
|||
} |
|||
|
|||
ol, |
|||
ul { |
|||
padding-left: 2rem; |
|||
} |
|||
|
|||
ol, |
|||
ul, |
|||
dl { |
|||
margin-top: 0; |
|||
margin-bottom: 1rem; |
|||
} |
|||
|
|||
ol ol, |
|||
ul ul, |
|||
ol ul, |
|||
ul ol { |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
dt { |
|||
font-weight: 700; |
|||
} |
|||
|
|||
dd { |
|||
margin-bottom: 0.5rem; |
|||
margin-left: 0; |
|||
} |
|||
|
|||
blockquote { |
|||
margin: 0 0 1rem; |
|||
} |
|||
|
|||
b, |
|||
strong { |
|||
font-weight: bolder; |
|||
} |
|||
|
|||
small { |
|||
font-size: 0.875em; |
|||
} |
|||
|
|||
mark { |
|||
padding: 0.2em; |
|||
background-color: #fcf8e3; |
|||
} |
|||
|
|||
sub, |
|||
sup { |
|||
position: relative; |
|||
font-size: 0.75em; |
|||
line-height: 0; |
|||
vertical-align: baseline; |
|||
} |
|||
|
|||
sub { |
|||
bottom: -0.25em; |
|||
} |
|||
|
|||
sup { |
|||
top: -0.5em; |
|||
} |
|||
|
|||
a { |
|||
color: #0d6efd; |
|||
text-decoration: underline; |
|||
} |
|||
a:hover { |
|||
color: #0a58ca; |
|||
} |
|||
|
|||
a:not([href]):not([class]), a:not([href]):not([class]):hover { |
|||
color: inherit; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
pre, |
|||
code, |
|||
kbd, |
|||
samp { |
|||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
|||
font-size: 1em; |
|||
direction: ltr /* rtl:ignore */; |
|||
unicode-bidi: bidi-override; |
|||
} |
|||
|
|||
pre { |
|||
display: block; |
|||
margin-top: 0; |
|||
margin-bottom: 1rem; |
|||
overflow: auto; |
|||
font-size: 0.875em; |
|||
} |
|||
pre code { |
|||
font-size: inherit; |
|||
color: inherit; |
|||
word-break: normal; |
|||
} |
|||
|
|||
code { |
|||
font-size: 0.875em; |
|||
color: #d63384; |
|||
word-wrap: break-word; |
|||
} |
|||
a > code { |
|||
color: inherit; |
|||
} |
|||
|
|||
kbd { |
|||
padding: 0.2rem 0.4rem; |
|||
font-size: 0.875em; |
|||
color: #fff; |
|||
background-color: #212529; |
|||
border-radius: 0.2rem; |
|||
} |
|||
kbd kbd { |
|||
padding: 0; |
|||
font-size: 1em; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
figure { |
|||
margin: 0 0 1rem; |
|||
} |
|||
|
|||
img, |
|||
svg { |
|||
vertical-align: middle; |
|||
} |
|||
|
|||
table { |
|||
caption-side: bottom; |
|||
border-collapse: collapse; |
|||
} |
|||
|
|||
caption { |
|||
padding-top: 0.5rem; |
|||
padding-bottom: 0.5rem; |
|||
color: #6c757d; |
|||
text-align: left; |
|||
} |
|||
|
|||
th { |
|||
text-align: inherit; |
|||
text-align: -webkit-match-parent; |
|||
} |
|||
|
|||
thead, |
|||
tbody, |
|||
tfoot, |
|||
tr, |
|||
td, |
|||
th { |
|||
border-color: inherit; |
|||
border-style: solid; |
|||
border-width: 0; |
|||
} |
|||
|
|||
label { |
|||
display: inline-block; |
|||
} |
|||
|
|||
button { |
|||
border-radius: 0; |
|||
} |
|||
|
|||
button:focus:not(:focus-visible) { |
|||
outline: 0; |
|||
} |
|||
|
|||
input, |
|||
button, |
|||
select, |
|||
optgroup, |
|||
textarea { |
|||
margin: 0; |
|||
font-family: inherit; |
|||
font-size: inherit; |
|||
line-height: inherit; |
|||
} |
|||
|
|||
button, |
|||
select { |
|||
text-transform: none; |
|||
} |
|||
|
|||
[role=button] { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
select { |
|||
word-wrap: normal; |
|||
} |
|||
select:disabled { |
|||
opacity: 1; |
|||
} |
|||
|
|||
[list]::-webkit-calendar-picker-indicator { |
|||
display: none; |
|||
} |
|||
|
|||
button, |
|||
[type=button], |
|||
[type=reset], |
|||
[type=submit] { |
|||
-webkit-appearance: button; |
|||
} |
|||
button:not(:disabled), |
|||
[type=button]:not(:disabled), |
|||
[type=reset]:not(:disabled), |
|||
[type=submit]:not(:disabled) { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
::-moz-focus-inner { |
|||
padding: 0; |
|||
border-style: none; |
|||
} |
|||
|
|||
textarea { |
|||
resize: vertical; |
|||
} |
|||
|
|||
fieldset { |
|||
min-width: 0; |
|||
padding: 0; |
|||
margin: 0; |
|||
border: 0; |
|||
} |
|||
|
|||
legend { |
|||
float: left; |
|||
width: 100%; |
|||
padding: 0; |
|||
margin-bottom: 0.5rem; |
|||
font-size: calc(1.275rem + 0.3vw); |
|||
line-height: inherit; |
|||
} |
|||
@media (min-width: 1200px) { |
|||
legend { |
|||
font-size: 1.5rem; |
|||
} |
|||
} |
|||
legend + * { |
|||
clear: left; |
|||
} |
|||
|
|||
::-webkit-datetime-edit-fields-wrapper, |
|||
::-webkit-datetime-edit-text, |
|||
::-webkit-datetime-edit-minute, |
|||
::-webkit-datetime-edit-hour-field, |
|||
::-webkit-datetime-edit-day-field, |
|||
::-webkit-datetime-edit-month-field, |
|||
::-webkit-datetime-edit-year-field { |
|||
padding: 0; |
|||
} |
|||
|
|||
::-webkit-inner-spin-button { |
|||
height: auto; |
|||
} |
|||
|
|||
[type=search] { |
|||
outline-offset: -2px; |
|||
-webkit-appearance: textfield; |
|||
} |
|||
|
|||
/* rtl:raw: |
|||
[type="tel"], |
|||
[type="url"], |
|||
[type="email"], |
|||
[type="number"] { |
|||
direction: ltr; |
|||
} |
|||
*/ |
|||
::-webkit-search-decoration { |
|||
-webkit-appearance: none; |
|||
} |
|||
|
|||
::-webkit-color-swatch-wrapper { |
|||
padding: 0; |
|||
} |
|||
|
|||
::file-selector-button { |
|||
font: inherit; |
|||
} |
|||
|
|||
::-webkit-file-upload-button { |
|||
font: inherit; |
|||
-webkit-appearance: button; |
|||
} |
|||
|
|||
output { |
|||
display: inline-block; |
|||
} |
|||
|
|||
iframe { |
|||
border: 0; |
|||
} |
|||
|
|||
summary { |
|||
display: list-item; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
progress { |
|||
vertical-align: baseline; |
|||
} |
|||
|
|||
[hidden] { |
|||
display: none !important; |
|||
} |
|||
|
|||
/*# sourceMappingURL=bootstrap-reboot.css.map */ |
|||
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@ |
|||
/*! |
|||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/) |
|||
* Copyright 2011-2021 The Bootstrap Authors |
|||
* Copyright 2011-2021 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
|||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
|||
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important} |
|||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */ |
|||
File diff suppressed because one or more lines are too long
@ -0,0 +1,424 @@ |
|||
/*! |
|||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/) |
|||
* Copyright 2011-2021 The Bootstrap Authors |
|||
* Copyright 2011-2021 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
|||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
|||
*/ |
|||
*, |
|||
*::before, |
|||
*::after { |
|||
box-sizing: border-box; |
|||
} |
|||
|
|||
@media (prefers-reduced-motion: no-preference) { |
|||
:root { |
|||
scroll-behavior: smooth; |
|||
} |
|||
} |
|||
|
|||
body { |
|||
margin: 0; |
|||
font-family: var(--bs-body-font-family); |
|||
font-size: var(--bs-body-font-size); |
|||
font-weight: var(--bs-body-font-weight); |
|||
line-height: var(--bs-body-line-height); |
|||
color: var(--bs-body-color); |
|||
text-align: var(--bs-body-text-align); |
|||
background-color: var(--bs-body-bg); |
|||
-webkit-text-size-adjust: 100%; |
|||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0); |
|||
} |
|||
|
|||
hr { |
|||
margin: 1rem 0; |
|||
color: inherit; |
|||
background-color: currentColor; |
|||
border: 0; |
|||
opacity: 0.25; |
|||
} |
|||
|
|||
hr:not([size]) { |
|||
height: 1px; |
|||
} |
|||
|
|||
h6, h5, h4, h3, h2, h1 { |
|||
margin-top: 0; |
|||
margin-bottom: 0.5rem; |
|||
font-weight: 500; |
|||
line-height: 1.2; |
|||
} |
|||
|
|||
h1 { |
|||
font-size: calc(1.375rem + 1.5vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h1 { |
|||
font-size: 2.5rem; |
|||
} |
|||
} |
|||
|
|||
h2 { |
|||
font-size: calc(1.325rem + 0.9vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h2 { |
|||
font-size: 2rem; |
|||
} |
|||
} |
|||
|
|||
h3 { |
|||
font-size: calc(1.3rem + 0.6vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h3 { |
|||
font-size: 1.75rem; |
|||
} |
|||
} |
|||
|
|||
h4 { |
|||
font-size: calc(1.275rem + 0.3vw); |
|||
} |
|||
@media (min-width: 1200px) { |
|||
h4 { |
|||
font-size: 1.5rem; |
|||
} |
|||
} |
|||
|
|||
h5 { |
|||
font-size: 1.25rem; |
|||
} |
|||
|
|||
h6 { |
|||
font-size: 1rem; |
|||
} |
|||
|
|||
p { |
|||
margin-top: 0; |
|||
margin-bottom: 1rem; |
|||
} |
|||
|
|||
abbr[title], |
|||
abbr[data-bs-original-title] { |
|||
-webkit-text-decoration: underline dotted; |
|||
text-decoration: underline dotted; |
|||
cursor: help; |
|||
-webkit-text-decoration-skip-ink: none; |
|||
text-decoration-skip-ink: none; |
|||
} |
|||
|
|||
address { |
|||
margin-bottom: 1rem; |
|||
font-style: normal; |
|||
line-height: inherit; |
|||
} |
|||
|
|||
ol, |
|||
ul { |
|||
padding-right: 2rem; |
|||
} |
|||
|
|||
ol, |
|||
ul, |
|||
dl { |
|||
margin-top: 0; |
|||
margin-bottom: 1rem; |
|||
} |
|||
|
|||
ol ol, |
|||
ul ul, |
|||
ol ul, |
|||
ul ol { |
|||
margin-bottom: 0; |
|||
} |
|||
|
|||
dt { |
|||
font-weight: 700; |
|||
} |
|||
|
|||
dd { |
|||
margin-bottom: 0.5rem; |
|||
margin-right: 0; |
|||
} |
|||
|
|||
blockquote { |
|||
margin: 0 0 1rem; |
|||
} |
|||
|
|||
b, |
|||
strong { |
|||
font-weight: bolder; |
|||
} |
|||
|
|||
small { |
|||
font-size: 0.875em; |
|||
} |
|||
|
|||
mark { |
|||
padding: 0.2em; |
|||
background-color: #fcf8e3; |
|||
} |
|||
|
|||
sub, |
|||
sup { |
|||
position: relative; |
|||
font-size: 0.75em; |
|||
line-height: 0; |
|||
vertical-align: baseline; |
|||
} |
|||
|
|||
sub { |
|||
bottom: -0.25em; |
|||
} |
|||
|
|||
sup { |
|||
top: -0.5em; |
|||
} |
|||
|
|||
a { |
|||
color: #0d6efd; |
|||
text-decoration: underline; |
|||
} |
|||
a:hover { |
|||
color: #0a58ca; |
|||
} |
|||
|
|||
a:not([href]):not([class]), a:not([href]):not([class]):hover { |
|||
color: inherit; |
|||
text-decoration: none; |
|||
} |
|||
|
|||
pre, |
|||
code, |
|||
kbd, |
|||
samp { |
|||
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
|||
font-size: 1em; |
|||
direction: ltr ; |
|||
unicode-bidi: bidi-override; |
|||
} |
|||
|
|||
pre { |
|||
display: block; |
|||
margin-top: 0; |
|||
margin-bottom: 1rem; |
|||
overflow: auto; |
|||
font-size: 0.875em; |
|||
} |
|||
pre code { |
|||
font-size: inherit; |
|||
color: inherit; |
|||
word-break: normal; |
|||
} |
|||
|
|||
code { |
|||
font-size: 0.875em; |
|||
color: #d63384; |
|||
word-wrap: break-word; |
|||
} |
|||
a > code { |
|||
color: inherit; |
|||
} |
|||
|
|||
kbd { |
|||
padding: 0.2rem 0.4rem; |
|||
font-size: 0.875em; |
|||
color: #fff; |
|||
background-color: #212529; |
|||
border-radius: 0.2rem; |
|||
} |
|||
kbd kbd { |
|||
padding: 0; |
|||
font-size: 1em; |
|||
font-weight: 700; |
|||
} |
|||
|
|||
figure { |
|||
margin: 0 0 1rem; |
|||
} |
|||
|
|||
img, |
|||
svg { |
|||
vertical-align: middle; |
|||
} |
|||
|
|||
table { |
|||
caption-side: bottom; |
|||
border-collapse: collapse; |
|||
} |
|||
|
|||
caption { |
|||
padding-top: 0.5rem; |
|||
padding-bottom: 0.5rem; |
|||
color: #6c757d; |
|||
text-align: right; |
|||
} |
|||
|
|||
th { |
|||
text-align: inherit; |
|||
text-align: -webkit-match-parent; |
|||
} |
|||
|
|||
thead, |
|||
tbody, |
|||
tfoot, |
|||
tr, |
|||
td, |
|||
th { |
|||
border-color: inherit; |
|||
border-style: solid; |
|||
border-width: 0; |
|||
} |
|||
|
|||
label { |
|||
display: inline-block; |
|||
} |
|||
|
|||
button { |
|||
border-radius: 0; |
|||
} |
|||
|
|||
button:focus:not(:focus-visible) { |
|||
outline: 0; |
|||
} |
|||
|
|||
input, |
|||
button, |
|||
select, |
|||
optgroup, |
|||
textarea { |
|||
margin: 0; |
|||
font-family: inherit; |
|||
font-size: inherit; |
|||
line-height: inherit; |
|||
} |
|||
|
|||
button, |
|||
select { |
|||
text-transform: none; |
|||
} |
|||
|
|||
[role=button] { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
select { |
|||
word-wrap: normal; |
|||
} |
|||
select:disabled { |
|||
opacity: 1; |
|||
} |
|||
|
|||
[list]::-webkit-calendar-picker-indicator { |
|||
display: none; |
|||
} |
|||
|
|||
button, |
|||
[type=button], |
|||
[type=reset], |
|||
[type=submit] { |
|||
-webkit-appearance: button; |
|||
} |
|||
button:not(:disabled), |
|||
[type=button]:not(:disabled), |
|||
[type=reset]:not(:disabled), |
|||
[type=submit]:not(:disabled) { |
|||
cursor: pointer; |
|||
} |
|||
|
|||
::-moz-focus-inner { |
|||
padding: 0; |
|||
border-style: none; |
|||
} |
|||
|
|||
textarea { |
|||
resize: vertical; |
|||
} |
|||
|
|||
fieldset { |
|||
min-width: 0; |
|||
padding: 0; |
|||
margin: 0; |
|||
border: 0; |
|||
} |
|||
|
|||
legend { |
|||
float: right; |
|||
width: 100%; |
|||
padding: 0; |
|||
margin-bottom: 0.5rem; |
|||
font-size: calc(1.275rem + 0.3vw); |
|||
line-height: inherit; |
|||
} |
|||
@media (min-width: 1200px) { |
|||
legend { |
|||
font-size: 1.5rem; |
|||
} |
|||
} |
|||
legend + * { |
|||
clear: right; |
|||
} |
|||
|
|||
::-webkit-datetime-edit-fields-wrapper, |
|||
::-webkit-datetime-edit-text, |
|||
::-webkit-datetime-edit-minute, |
|||
::-webkit-datetime-edit-hour-field, |
|||
::-webkit-datetime-edit-day-field, |
|||
::-webkit-datetime-edit-month-field, |
|||
::-webkit-datetime-edit-year-field { |
|||
padding: 0; |
|||
} |
|||
|
|||
::-webkit-inner-spin-button { |
|||
height: auto; |
|||
} |
|||
|
|||
[type=search] { |
|||
outline-offset: -2px; |
|||
-webkit-appearance: textfield; |
|||
} |
|||
|
|||
[type="tel"], |
|||
[type="url"], |
|||
[type="email"], |
|||
[type="number"] { |
|||
direction: ltr; |
|||
} |
|||
::-webkit-search-decoration { |
|||
-webkit-appearance: none; |
|||
} |
|||
|
|||
::-webkit-color-swatch-wrapper { |
|||
padding: 0; |
|||
} |
|||
|
|||
::file-selector-button { |
|||
font: inherit; |
|||
} |
|||
|
|||
::-webkit-file-upload-button { |
|||
font: inherit; |
|||
-webkit-appearance: button; |
|||
} |
|||
|
|||
output { |
|||
display: inline-block; |
|||
} |
|||
|
|||
iframe { |
|||
border: 0; |
|||
} |
|||
|
|||
summary { |
|||
display: list-item; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
progress { |
|||
vertical-align: baseline; |
|||
} |
|||
|
|||
[hidden] { |
|||
display: none !important; |
|||
} |
|||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */ |
|||
File diff suppressed because one or more lines are too long
@ -0,0 +1,8 @@ |
|||
/*! |
|||
* Bootstrap Reboot v5.1.0 (https://getbootstrap.com/) |
|||
* Copyright 2011-2021 The Bootstrap Authors |
|||
* Copyright 2011-2021 Twitter, Inc. |
|||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) |
|||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) |
|||
*/*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:var(--bs-body-font-family);font-size:var(--bs-body-font-size);font-weight:var(--bs-body-font-weight);line-height:var(--bs-body-line-height);color:var(--bs-body-color);text-align:var(--bs-body-text-align);background-color:var(--bs-body-bg);-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-right:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-right:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:right}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:right;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:right}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}[type=email],[type=number],[type=tel],[type=url]{direction:ltr}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important} |
|||
/*# sourceMappingURL=bootstrap-reboot.rtl.min.css.map */ |
|||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue