@ -0,0 +1,184 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> | |||
<ProductVersion>8.0.30703</ProductVersion> | |||
<SchemaVersion>2.0</SchemaVersion> | |||
<ProjectGuid>{A289A7F0-ACD8-42AE-87B6-AB1AFD310BF1}</ProjectGuid> | |||
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | |||
<OutputType>Library</OutputType> | |||
<AppDesignerFolder>Properties</AppDesignerFolder> | |||
<RootNamespace>eShopOnContainers.TestRunner.Droid</RootNamespace> | |||
<AssemblyName>eShopOnContainers.TestRunner.Droid</AssemblyName> | |||
<FileAlignment>512</FileAlignment> | |||
<AndroidApplication>true</AndroidApplication> | |||
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile> | |||
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies> | |||
<AndroidUseLatestPlatformSdk>True</AndroidUseLatestPlatformSdk> | |||
<TargetFrameworkVersion>v7.0</TargetFrameworkVersion> | |||
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest> | |||
<NuGetPackageImportStamp> | |||
</NuGetPackageImportStamp> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\Debug\</OutputPath> | |||
<DefineConstants>DEBUG;TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime> | |||
<AndroidLinkMode>None</AndroidLinkMode> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> | |||
<DebugType>pdbonly</DebugType> | |||
<DebugSymbols>true</DebugSymbols> | |||
<AndroidManagedSymbols>true</AndroidManagedSymbols> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\Release\</OutputPath> | |||
<DefineConstants>TRACE</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime> | |||
<AndroidLinkMode>SdkOnly</AndroidLinkMode> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Reference Include="FormsViewGroup, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\MonoAndroid10\FormsViewGroup.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Mono.Android" /> | |||
<Reference Include="mscorlib" /> | |||
<Reference Include="System" /> | |||
<Reference Include="System.Core" /> | |||
<Reference Include="System.Xml.Linq" /> | |||
<Reference Include="System.Xml" /> | |||
<Reference Include="Xamarin.Android.Support.Animated.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Animated.Vector.Drawable.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.Design, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.Design.23.3.0\lib\MonoAndroid43\Xamarin.Android.Support.Design.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.v4, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.v4.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v4.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.v7.AppCompat, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.v7.AppCompat.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.AppCompat.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.v7.CardView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.v7.CardView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.CardView.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.v7.MediaRouter, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.v7.MediaRouter.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.MediaRouter.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.v7.RecyclerView, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.v7.RecyclerView.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.v7.RecyclerView.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Android.Support.Vector.Drawable, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\lib\MonoAndroid403\Xamarin.Android.Support.Vector.Drawable.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\MonoAndroid10\Xamarin.Forms.Core.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\MonoAndroid10\Xamarin.Forms.Platform.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Platform.Android, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\MonoAndroid10\Xamarin.Forms.Platform.Android.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Xaml, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\MonoAndroid10\Xamarin.Forms.Xaml.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.assert, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.assert.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.assert.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.core, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.extensibility.core.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.core.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.execution.dotnet, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.extensibility.execution.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.execution.dotnet.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.runner.devices, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.runner.devices.2.1.0\lib\MonoAndroid\xunit.runner.devices.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.runner.utility.dotnet, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.runner.utility.2.2.0-beta4-build3444\lib\netstandard1.1\xunit.runner.utility.dotnet.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Compile Include="MainActivity.cs" /> | |||
<Compile Include="Resources\Resource.Designer.cs" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="app.config" /> | |||
<None Include="packages.config" /> | |||
<None Include="Resources\AboutResources.txt" /> | |||
<None Include="Assets\AboutAssets.txt" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<AndroidResource Include="Resources\layout\Main.axml"> | |||
<SubType>Designer</SubType> | |||
</AndroidResource> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<AndroidResource Include="Resources\values\Strings.xml" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<AndroidResource Include="Resources\drawable\Icon.png" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<None Include="Properties\AndroidManifest.xml" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Content Include="MainActivity.cs.txt" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj"> | |||
<Project>{f7b6a162-bc4d-4924-b16a-713f9b0344e7}</Project> | |||
<Name>eShopOnContainers.UnitTests</Name> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> | |||
<Import Project="..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets" Condition="Exists('..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets')" /> | |||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||
<PropertyGroup> | |||
<ErrorText>Este proyecto hace referencia a los paquetes NuGet que faltan en este equipo. Use la restauración de paquetes NuGet para descargarlos. Para obtener más información, consulte http://go.microsoft.com/fwlink/?LinkID=322105. El archivo que falta es {0}.</ErrorText> | |||
</PropertyGroup> | |||
<Error Condition="!Exists('..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Xamarin.Android.Support.Vector.Drawable.23.3.0\build\Xamarin.Android.Support.Vector.Drawable.targets'))" /> | |||
<Error Condition="!Exists('..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets'))" /> | |||
<Error Condition="!Exists('..\..\packages\xunit.runner.devices.2.1.0\build\MonoAndroid\xunit.runner.devices.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.runner.devices.2.1.0\build\MonoAndroid\xunit.runner.devices.targets'))" /> | |||
</Target> | |||
<Import Project="..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets')" /> | |||
<Import Project="..\..\packages\xunit.runner.devices.2.1.0\build\MonoAndroid\xunit.runner.devices.targets" Condition="Exists('..\..\packages\xunit.runner.devices.2.1.0\build\MonoAndroid\xunit.runner.devices.targets')" /> | |||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. | |||
Other similar extension points exist, see Microsoft.Common.targets. | |||
<Target Name="BeforeBuild"> | |||
</Target> | |||
<Target Name="AfterBuild"> | |||
</Target> | |||
--> | |||
</Project> |
@ -0,0 +1,175 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> | |||
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform> | |||
<ProjectGuid>{B68C2B56-7581-46AE-B55D-D25DDFD3BFE3}</ProjectGuid> | |||
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> | |||
<OutputType>Exe</OutputType> | |||
<RootNamespace>eShopOnContainers.TestRunner.iOS</RootNamespace> | |||
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix> | |||
<AssemblyName>eShopOnContainersTestRunner.iOS</AssemblyName> | |||
<NuGetPackageImportStamp> | |||
</NuGetPackageImportStamp> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\iPhoneSimulator\Debug</OutputPath> | |||
<DefineConstants>DEBUG</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<ConsolePause>false</ConsolePause> | |||
<MtouchArch>x86_64</MtouchArch> | |||
<MtouchLink>SdkOnly</MtouchLink> | |||
<MtouchDebug>True</MtouchDebug> | |||
<MtouchSdkVersion>10.1</MtouchSdkVersion> | |||
<MtouchProfiling>False</MtouchProfiling> | |||
<MtouchFastDev>False</MtouchFastDev> | |||
<MtouchUseLlvm>False</MtouchUseLlvm> | |||
<MtouchUseThumb>False</MtouchUseThumb> | |||
<MtouchEnableBitcode>False</MtouchEnableBitcode> | |||
<MtouchUseSGen>False</MtouchUseSGen> | |||
<MtouchUseRefCounting>False</MtouchUseRefCounting> | |||
<OptimizePNGs>True</OptimizePNGs> | |||
<MtouchTlsProvider>Default</MtouchTlsProvider> | |||
<MtouchHttpClientHandler>HttpClientHandler</MtouchHttpClientHandler> | |||
<MtouchFloat32>False</MtouchFloat32> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' "> | |||
<DebugType>none</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\iPhoneSimulator\Release</OutputPath> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<MtouchLink>None</MtouchLink> | |||
<MtouchArch>x86_64</MtouchArch> | |||
<ConsolePause>false</ConsolePause> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' "> | |||
<DebugSymbols>true</DebugSymbols> | |||
<DebugType>full</DebugType> | |||
<Optimize>false</Optimize> | |||
<OutputPath>bin\iPhone\Debug</OutputPath> | |||
<DefineConstants>DEBUG</DefineConstants> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<ConsolePause>false</ConsolePause> | |||
<MtouchArch>ARMv7, ARM64</MtouchArch> | |||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> | |||
<CodesignKey>iPhone Developer</CodesignKey> | |||
<MtouchDebug>true</MtouchDebug> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' "> | |||
<DebugType>none</DebugType> | |||
<Optimize>true</Optimize> | |||
<OutputPath>bin\iPhone\Release</OutputPath> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> | |||
<MtouchArch>ARMv7, ARM64</MtouchArch> | |||
<ConsolePause>false</ConsolePause> | |||
<CodesignKey>iPhone Developer</CodesignKey> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Ad-Hoc|iPhone' "> | |||
<DebugType>none</DebugType> | |||
<Optimize>True</Optimize> | |||
<OutputPath>bin\iPhone\Ad-Hoc</OutputPath> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<ConsolePause>False</ConsolePause> | |||
<MtouchArch>ARMv7, ARM64</MtouchArch> | |||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> | |||
<BuildIpa>True</BuildIpa> | |||
<CodesignProvision>Automatic:AdHoc</CodesignProvision> | |||
<CodesignKey>iPhone Distribution</CodesignKey> | |||
</PropertyGroup> | |||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'AppStore|iPhone' "> | |||
<DebugType>none</DebugType> | |||
<Optimize>True</Optimize> | |||
<OutputPath>bin\iPhone\AppStore</OutputPath> | |||
<ErrorReport>prompt</ErrorReport> | |||
<WarningLevel>4</WarningLevel> | |||
<ConsolePause>False</ConsolePause> | |||
<MtouchArch>ARMv7, ARM64</MtouchArch> | |||
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements> | |||
<CodesignProvision>Automatic:AppStore</CodesignProvision> | |||
<CodesignKey>iPhone Distribution</CodesignKey> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<Compile Include="Main.cs" /> | |||
<Compile Include="AppDelegate.cs" /> | |||
<None Include="app.config" /> | |||
<None Include="Info.plist" /> | |||
<Compile Include="Properties\AssemblyInfo.cs" /> | |||
<InterfaceDefinition Include="Resources\LaunchScreen.xib" /> | |||
<None Include="packages.config" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Reference Include="System" /> | |||
<Reference Include="System.Xml" /> | |||
<Reference Include="System.Core" /> | |||
<Reference Include="Xamarin.Forms.Core, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Core.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Platform, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Platform.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Platform.iOS, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Platform.iOS.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.Forms.Xaml, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\Xamarin.Forms.2.3.3.166-pre4\lib\Xamarin.iOS10\Xamarin.Forms.Xaml.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="Xamarin.iOS" /> | |||
<Reference Include="xunit.abstractions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.abstractions.2.0.1\lib\netstandard1.0\xunit.abstractions.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.assert, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.assert.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.assert.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.core, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.extensibility.core.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.core.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.execution.dotnet, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.extensibility.execution.2.2.0-beta4-build3444\lib\netstandard1.0\xunit.execution.dotnet.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.runner.devices, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.runner.devices.2.1.0\lib\Xamarin.iOS\xunit.runner.devices.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
<Reference Include="xunit.runner.utility.dotnet, Version=2.2.0.3444, Culture=neutral, PublicKeyToken=8d05b1bb7a6fdb6c, processorArchitecture=MSIL"> | |||
<HintPath>..\..\packages\xunit.runner.utility.2.2.0-beta4-build3444\lib\netstandard1.1\xunit.runner.utility.dotnet.dll</HintPath> | |||
<Private>True</Private> | |||
</Reference> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<Content Include="AppDelegate.cs.txt" /> | |||
<Content Include="Entitlements.plist" /> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ProjectReference Include="..\eShopOnContainers.UnitTests\eShopOnContainers.UnitTests.csproj"> | |||
<Project>{f7b6a162-bc4d-4924-b16a-713f9b0344e7}</Project> | |||
<Name>eShopOnContainers.UnitTests</Name> | |||
</ProjectReference> | |||
</ItemGroup> | |||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> | |||
<Import Project="..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets" Condition="Exists('..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets')" /> | |||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> | |||
<PropertyGroup> | |||
<ErrorText>Este proyecto hace referencia a los paquetes NuGet que faltan en este equipo. Use la restauración de paquetes NuGet para descargarlos. Para obtener más información, consulte http://go.microsoft.com/fwlink/?LinkID=322105. El archivo que falta es {0}.</ErrorText> | |||
</PropertyGroup> | |||
<Error Condition="!Exists('..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Xamarin.Forms.2.3.3.166-pre4\build\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.targets'))" /> | |||
<Error Condition="!Exists('..\..\packages\xunit.runner.devices.2.1.0\build\Xamarin.iOS\xunit.runner.devices.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\xunit.runner.devices.2.1.0\build\Xamarin.iOS\xunit.runner.devices.targets'))" /> | |||
</Target> | |||
<Import Project="..\..\packages\xunit.runner.devices.2.1.0\build\Xamarin.iOS\xunit.runner.devices.targets" Condition="Exists('..\..\packages\xunit.runner.devices.2.1.0\build\Xamarin.iOS\xunit.runner.devices.targets')" /> | |||
</Project> |
@ -0,0 +1,3 @@ | |||
{ | |||
"directory": "wwwroot/lib" | |||
} |
@ -0,0 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Configuration | |||
{ | |||
public class ClientCallBackUrls | |||
{ | |||
public string Spa { get; set; } | |||
} | |||
} |
@ -0,0 +1,68 @@ | |||
using IdentityServer4.Models; | |||
using Microsoft.Extensions.Options; | |||
using System.Collections.Generic; | |||
namespace eShopOnContainers.Identity.Configuration | |||
{ | |||
public class Config | |||
{ | |||
private readonly IOptions<ClientCallBackUrls> _settings; | |||
public Config(IOptions<ClientCallBackUrls> settings) | |||
{ | |||
_settings = settings; | |||
} | |||
// scopes define the resources in your system | |||
public static IEnumerable<Scope> GetScopes() | |||
{ | |||
return new List<Scope> | |||
{ | |||
//Authentication OpenId uses this scopes; | |||
StandardScopes.OpenId, | |||
StandardScopes.Profile, | |||
//Each api we want to securice; | |||
new Scope | |||
{ | |||
Name = "orders", | |||
Description = "Orders Service" | |||
}, | |||
new Scope | |||
{ | |||
Name = "basket", | |||
Description = "Basket Service" | |||
} | |||
}; | |||
} | |||
// client want to access resources (aka scopes) | |||
public static IEnumerable<Client> GetClients() | |||
{ | |||
return new List<Client> | |||
{ | |||
// JavaScript Client | |||
new Client | |||
{ | |||
ClientId = "js", | |||
ClientName = "eShop SPA OpenId Client", | |||
AllowedGrantTypes = GrantTypes.Implicit, | |||
AllowAccessTokensViaBrowser = true, | |||
RedirectUris = { "http://localhost:5003/callback.html" }, | |||
PostLogoutRedirectUris = { "http://localhost:5003/index.html" }, | |||
AllowedCorsOrigins = { "http://localhost:5003" }, | |||
AllowedScopes = | |||
{ | |||
StandardScopes.OpenId.Name, | |||
StandardScopes.Profile.Name, | |||
"orders", | |||
"basket" | |||
} | |||
} | |||
}; | |||
} | |||
} | |||
} |
@ -0,0 +1,333 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using IdentityModel; | |||
using IdentityServer4.Quickstart.UI.Models; | |||
using IdentityServer4.Services; | |||
using IdentityServer4.Services.InMemory; | |||
using Microsoft.AspNetCore.Http.Authentication; | |||
using Microsoft.AspNetCore.Mvc; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Security.Claims; | |||
using System.Text.Encodings.Web; | |||
using System.Threading.Tasks; | |||
using IdentityServer4.Models; | |||
using IdentityServer4.Stores; | |||
using eShopOnContainers.Identity.Services; | |||
using eShopOnContainers.Identity.Models; | |||
using Microsoft.Extensions.Logging; | |||
namespace IdentityServer4.Quickstart.UI.Controllers | |||
{ | |||
/// <summary> | |||
/// This sample controller implements a typical login/logout/provision workflow for local and external accounts. | |||
/// The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production! | |||
/// The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval | |||
/// </summary> | |||
public class AccountController : Controller | |||
{ | |||
//private readonly InMemoryUserLoginService _loginService; | |||
private readonly ILoginService<ApplicationUser> _loginService; | |||
private readonly IIdentityServerInteractionService _interaction; | |||
private readonly IClientStore _clientStore; | |||
private readonly ILogger _logger; | |||
public AccountController( | |||
//InMemoryUserLoginService loginService, | |||
ILoginService<ApplicationUser> loginService, | |||
IIdentityServerInteractionService interaction, | |||
IClientStore clientStore, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
_loginService = loginService; | |||
_interaction = interaction; | |||
_clientStore = clientStore; | |||
_logger = loggerFactory.CreateLogger<AccountController>(); | |||
} | |||
/// <summary> | |||
/// Show login page | |||
/// </summary> | |||
[HttpGet] | |||
public async Task<IActionResult> Login(string returnUrl) | |||
{ | |||
var context = await _interaction.GetAuthorizationContextAsync(returnUrl); | |||
if (context?.IdP != null) | |||
{ | |||
// if IdP is passed, then bypass showing the login screen | |||
return ExternalLogin(context.IdP, returnUrl); | |||
} | |||
var vm = await BuildLoginViewModelAsync(returnUrl, context); | |||
if (vm.EnableLocalLogin == false && vm.ExternalProviders.Count() == 1) | |||
{ | |||
// only one option for logging in | |||
return ExternalLogin(vm.ExternalProviders.First().AuthenticationScheme, returnUrl); | |||
} | |||
return View(vm); | |||
} | |||
/// <summary> | |||
/// Handle postback from username/password login | |||
/// </summary> | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> Login(LoginInputModel model) | |||
{ | |||
if (ModelState.IsValid) | |||
{ | |||
var user = await _loginService.FindByUsername(model.Username); | |||
// validate username/password against in-memory store | |||
if (await _loginService.ValidateCredentials(user, model.Password)) | |||
{ | |||
// issue authentication cookie with subject ID and username | |||
//var user = _loginService.FindByUsername(model.Username); | |||
AuthenticationProperties props = null; | |||
// only set explicit expiration here if persistent. | |||
// otherwise we reply upon expiration configured in cookie middleware. | |||
if (model.RememberLogin) | |||
{ | |||
props = new AuthenticationProperties | |||
{ | |||
IsPersistent = true, | |||
ExpiresUtc = DateTimeOffset.UtcNow.AddMonths(1) | |||
}; | |||
}; | |||
//await HttpContext.Authentication.SignInAsync(, user.UserName, props); | |||
await _loginService.SignIn(user); | |||
// make sure the returnUrl is still valid, and if yes - redirect back to authorize endpoint | |||
if (_interaction.IsValidReturnUrl(model.ReturnUrl)) | |||
{ | |||
return Redirect(model.ReturnUrl); | |||
} | |||
return Redirect("~/"); | |||
} | |||
ModelState.AddModelError("", "Invalid username or password."); | |||
} | |||
// something went wrong, show form with error | |||
var vm = await BuildLoginViewModelAsync(model); | |||
return View(vm); | |||
} | |||
async Task<LoginViewModel> BuildLoginViewModelAsync(string returnUrl, AuthorizationRequest context) | |||
{ | |||
var providers = HttpContext.Authentication.GetAuthenticationSchemes() | |||
.Where(x => x.DisplayName != null) | |||
.Select(x => new ExternalProvider | |||
{ | |||
DisplayName = x.DisplayName, | |||
AuthenticationScheme = x.AuthenticationScheme | |||
}); | |||
var allowLocal = true; | |||
if (context?.ClientId != null) | |||
{ | |||
var client = await _clientStore.FindEnabledClientByIdAsync(context.ClientId); | |||
if (client != null) | |||
{ | |||
allowLocal = client.EnableLocalLogin; | |||
if (client.IdentityProviderRestrictions != null && client.IdentityProviderRestrictions.Any()) | |||
{ | |||
providers = providers.Where(provider => client.IdentityProviderRestrictions.Contains(provider.AuthenticationScheme)); | |||
} | |||
} | |||
} | |||
return new LoginViewModel | |||
{ | |||
EnableLocalLogin = allowLocal, | |||
ReturnUrl = returnUrl, | |||
Username = context?.LoginHint, | |||
ExternalProviders = providers.ToArray() | |||
}; | |||
} | |||
async Task<LoginViewModel> BuildLoginViewModelAsync(LoginInputModel model) | |||
{ | |||
var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); | |||
var vm = await BuildLoginViewModelAsync(model.ReturnUrl, context); | |||
vm.Username = model.Username; | |||
vm.RememberLogin = model.RememberLogin; | |||
return vm; | |||
} | |||
/// <summary> | |||
/// Show logout page | |||
/// </summary> | |||
[HttpGet] | |||
public async Task<IActionResult> Logout(string logoutId) | |||
{ | |||
if (User.Identity.IsAuthenticated == false) | |||
{ | |||
// if the user is not authenticated, then just show logged out page | |||
return await Logout(new LogoutViewModel { LogoutId = logoutId }); | |||
} | |||
var context = await _interaction.GetLogoutContextAsync(logoutId); | |||
if (context?.ShowSignoutPrompt == false) | |||
{ | |||
// it's safe to automatically sign-out | |||
return await Logout(new LogoutViewModel { LogoutId = logoutId }); | |||
} | |||
// show the logout prompt. this prevents attacks where the user | |||
// is automatically signed out by another malicious web page. | |||
var vm = new LogoutViewModel | |||
{ | |||
LogoutId = logoutId | |||
}; | |||
return View(vm); | |||
} | |||
/// <summary> | |||
/// Handle logout page postback | |||
/// </summary> | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> Logout(LogoutViewModel model) | |||
{ | |||
var idp = User?.FindFirst(JwtClaimTypes.IdentityProvider)?.Value; | |||
if (idp != null && idp != IdentityServerConstants.LocalIdentityProvider) | |||
{ | |||
if (model.LogoutId == null) | |||
{ | |||
// if there's no current logout context, we need to create one | |||
// this captures necessary info from the current logged in user | |||
// before we signout and redirect away to the external IdP for signout | |||
model.LogoutId = await _interaction.CreateLogoutContextAsync(); | |||
} | |||
string url = "/Account/Logout?logoutId=" + model.LogoutId; | |||
try | |||
{ | |||
// hack: try/catch to handle social providers that throw | |||
await HttpContext.Authentication.SignOutAsync(idp, new AuthenticationProperties { RedirectUri = url }); | |||
} | |||
catch(NotSupportedException) | |||
{ | |||
} | |||
} | |||
// delete authentication cookie | |||
await HttpContext.Authentication.SignOutAsync(); | |||
// set this so UI rendering sees an anonymous user | |||
HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); | |||
// get context information (client name, post logout redirect URI and iframe for federated signout) | |||
var logout = await _interaction.GetLogoutContextAsync(model.LogoutId); | |||
var vm = new LoggedOutViewModel | |||
{ | |||
PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, | |||
ClientName = logout?.ClientId, | |||
SignOutIframeUrl = logout?.SignOutIFrameUrl | |||
}; | |||
return View("LoggedOut", vm); | |||
} | |||
/// <summary> | |||
/// initiate roundtrip to external authentication provider | |||
/// </summary> | |||
[HttpGet] | |||
public IActionResult ExternalLogin(string provider, string returnUrl) | |||
{ | |||
if (returnUrl != null) | |||
{ | |||
returnUrl = UrlEncoder.Default.Encode(returnUrl); | |||
} | |||
returnUrl = "/account/externallogincallback?returnUrl=" + returnUrl; | |||
// start challenge and roundtrip the return URL | |||
var props = new AuthenticationProperties | |||
{ | |||
RedirectUri = returnUrl, | |||
Items = { { "scheme", provider } } | |||
}; | |||
return new ChallengeResult(provider, props); | |||
} | |||
/// <summary> | |||
/// Post processing of external authentication | |||
/// </summary> | |||
[HttpGet] | |||
public async Task<IActionResult> ExternalLoginCallback(string returnUrl) | |||
{ | |||
// read external identity from the temporary cookie | |||
var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); | |||
//var tempUser = info?.Principal; | |||
//if (tempUser == null) | |||
//{ | |||
// throw new Exception("External authentication error"); | |||
//} | |||
//// retrieve claims of the external user | |||
//var claims = tempUser.Claims.ToList(); | |||
//// try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier | |||
//// depending on the external provider, some other claim type might be used | |||
//var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject); | |||
//if (userIdClaim == null) | |||
//{ | |||
// userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier); | |||
//} | |||
//if (userIdClaim == null) | |||
//{ | |||
// throw new Exception("Unknown userid"); | |||
//} | |||
//// remove the user id claim from the claims collection and move to the userId property | |||
//// also set the name of the external authentication provider | |||
//claims.Remove(userIdClaim); | |||
//var provider = info.Properties.Items["scheme"]; | |||
//var userId = userIdClaim.Value; | |||
//// check if the external user is already provisioned | |||
//var user = _loginService.FindByExternalProvider(provider, userId); | |||
//if (user == null) | |||
//{ | |||
// // this sample simply auto-provisions new external user | |||
// // another common approach is to start a registrations workflow first | |||
// user = _loginService.AutoProvisionUser(provider, userId, claims); | |||
//} | |||
//var additionalClaims = new List<Claim>(); | |||
//// if the external system sent a session id claim, copy it over | |||
//var sid = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.SessionId); | |||
//if (sid != null) | |||
//{ | |||
// additionalClaims.Add(new Claim(JwtClaimTypes.SessionId, sid.Value)); | |||
//} | |||
//// issue authentication cookie for user | |||
//await HttpContext.Authentication.SignInAsync(user.Subject, user.Username, provider, additionalClaims.ToArray()); | |||
//// delete temporary cookie used during external authentication | |||
//await HttpContext.Authentication.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); | |||
//// validate return URL and redirect back to authorization endpoint | |||
//if (_interaction.IsValidReturnUrl(returnUrl)) | |||
//{ | |||
// return Redirect(returnUrl); | |||
//} | |||
return Redirect("~/"); | |||
} | |||
} | |||
} |
@ -0,0 +1,142 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using IdentityServer4.Services; | |||
using Microsoft.AspNetCore.Mvc; | |||
using Microsoft.Extensions.Logging; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using IdentityServer4.Models; | |||
using IdentityServer4.Stores; | |||
using IdentityServer4.Quickstart.UI.Models; | |||
namespace IdentityServer4.Quickstart.UI.Controllers | |||
{ | |||
/// <summary> | |||
/// This controller implements the consent logic | |||
/// </summary> | |||
public class ConsentController : Controller | |||
{ | |||
private readonly ILogger<ConsentController> _logger; | |||
private readonly IClientStore _clientStore; | |||
private readonly IScopeStore _scopeStore; | |||
private readonly IIdentityServerInteractionService _interaction; | |||
public ConsentController( | |||
ILogger<ConsentController> logger, | |||
IIdentityServerInteractionService interaction, | |||
IClientStore clientStore, | |||
IScopeStore scopeStore) | |||
{ | |||
_logger = logger; | |||
_interaction = interaction; | |||
_clientStore = clientStore; | |||
_scopeStore = scopeStore; | |||
} | |||
/// <summary> | |||
/// Shows the consent screen | |||
/// </summary> | |||
/// <param name="returnUrl"></param> | |||
/// <returns></returns> | |||
[HttpGet] | |||
public async Task<IActionResult> Index(string returnUrl) | |||
{ | |||
var vm = await BuildViewModelAsync(returnUrl); | |||
if (vm != null) | |||
{ | |||
return View("Index", vm); | |||
} | |||
return View("Error"); | |||
} | |||
/// <summary> | |||
/// Handles the consent screen postback | |||
/// </summary> | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> Index(ConsentInputModel model) | |||
{ | |||
// parse the return URL back to an AuthorizeRequest object | |||
var request = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl); | |||
ConsentResponse response = null; | |||
// user clicked 'no' - send back the standard 'access_denied' response | |||
if (model.Button == "no") | |||
{ | |||
response = ConsentResponse.Denied; | |||
} | |||
// user clicked 'yes' - validate the data | |||
else if (model.Button == "yes" && model != null) | |||
{ | |||
// if the user consented to some scope, build the response model | |||
if (model.ScopesConsented != null && model.ScopesConsented.Any()) | |||
{ | |||
response = new ConsentResponse | |||
{ | |||
RememberConsent = model.RememberConsent, | |||
ScopesConsented = model.ScopesConsented | |||
}; | |||
} | |||
else | |||
{ | |||
ModelState.AddModelError("", "You must pick at least one permission."); | |||
} | |||
} | |||
else | |||
{ | |||
ModelState.AddModelError("", "Invalid Selection"); | |||
} | |||
if (response != null) | |||
{ | |||
// communicate outcome of consent back to identityserver | |||
await _interaction.GrantConsentAsync(request, response); | |||
// redirect back to authorization endpoint | |||
return Redirect(model.ReturnUrl); | |||
} | |||
var vm = await BuildViewModelAsync(model.ReturnUrl, model); | |||
if (vm != null) | |||
{ | |||
return View("Index", vm); | |||
} | |||
return View("Error"); | |||
} | |||
async Task<ConsentViewModel> BuildViewModelAsync(string returnUrl, ConsentInputModel model = null) | |||
{ | |||
var request = await _interaction.GetAuthorizationContextAsync(returnUrl); | |||
if (request != null) | |||
{ | |||
var client = await _clientStore.FindEnabledClientByIdAsync(request.ClientId); | |||
if (client != null) | |||
{ | |||
var scopes = await _scopeStore.FindEnabledScopesAsync(request.ScopesRequested); | |||
if (scopes != null && scopes.Any()) | |||
{ | |||
return new ConsentViewModel(model, returnUrl, request, client, scopes); | |||
} | |||
else | |||
{ | |||
_logger.LogError("No scopes matching: {0}", request.ScopesRequested.Aggregate((x, y) => x + ", " + y)); | |||
} | |||
} | |||
else | |||
{ | |||
_logger.LogError("Invalid client id: {0}", request.ClientId); | |||
} | |||
} | |||
else | |||
{ | |||
_logger.LogError("No consent request matching request: {0}", returnUrl); | |||
} | |||
return null; | |||
} | |||
} | |||
} |
@ -0,0 +1,43 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using IdentityServer4.Quickstart.UI.Models; | |||
using IdentityServer4.Services; | |||
using Microsoft.AspNetCore.Mvc; | |||
using System.Threading.Tasks; | |||
namespace IdentityServer4.Quickstart.UI.Controllers | |||
{ | |||
public class HomeController : Controller | |||
{ | |||
private readonly IIdentityServerInteractionService _interaction; | |||
public HomeController(IIdentityServerInteractionService interaction) | |||
{ | |||
_interaction = interaction; | |||
} | |||
public IActionResult Index() | |||
{ | |||
return View(); | |||
} | |||
/// <summary> | |||
/// Shows the error page | |||
/// </summary> | |||
public async Task<IActionResult> Error(string errorId) | |||
{ | |||
var vm = new ErrorViewModel(); | |||
// retrieve error details from identityserver | |||
var message = await _interaction.GetErrorContextAsync(errorId); | |||
if (message != null) | |||
{ | |||
vm.Error = message; | |||
} | |||
return View("Error", vm); | |||
} | |||
} | |||
} |
@ -0,0 +1,360 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Authorization; | |||
using Microsoft.AspNetCore.Identity; | |||
using Microsoft.AspNetCore.Mvc; | |||
using Microsoft.Extensions.Logging; | |||
using eShopOnContainers.Identity.Models; | |||
using eShopOnContainers.Identity.Models.ManageViewModels; | |||
using eShopOnContainers.Identity.Services; | |||
namespace eShopOnContainers.Identity.Controllers | |||
{ | |||
[Authorize] | |||
public class ManageController : Controller | |||
{ | |||
private readonly UserManager<ApplicationUser> _userManager; | |||
private readonly SignInManager<ApplicationUser> _signInManager; | |||
private readonly IEmailSender _emailSender; | |||
private readonly ISmsSender _smsSender; | |||
private readonly ILogger _logger; | |||
public ManageController( | |||
UserManager<ApplicationUser> userManager, | |||
SignInManager<ApplicationUser> signInManager, | |||
IEmailSender emailSender, | |||
ISmsSender smsSender, | |||
ILoggerFactory loggerFactory) | |||
{ | |||
_userManager = userManager; | |||
_signInManager = signInManager; | |||
_emailSender = emailSender; | |||
_smsSender = smsSender; | |||
_logger = loggerFactory.CreateLogger<ManageController>(); | |||
} | |||
// | |||
// GET: /Manage/Index | |||
[HttpGet] | |||
public async Task<IActionResult> Index(ManageMessageId? message = null) | |||
{ | |||
ViewData["StatusMessage"] = | |||
message == ManageMessageId.ChangePasswordSuccess ? "Your password has been changed." | |||
: message == ManageMessageId.SetPasswordSuccess ? "Your password has been set." | |||
: message == ManageMessageId.SetTwoFactorSuccess ? "Your two-factor authentication provider has been set." | |||
: message == ManageMessageId.Error ? "An error has occurred." | |||
: message == ManageMessageId.AddPhoneSuccess ? "Your phone number was added." | |||
: message == ManageMessageId.RemovePhoneSuccess ? "Your phone number was removed." | |||
: ""; | |||
var user = await GetCurrentUserAsync(); | |||
if (user == null) | |||
{ | |||
return View("Error"); | |||
} | |||
var model = new IndexViewModel | |||
{ | |||
HasPassword = await _userManager.HasPasswordAsync(user), | |||
PhoneNumber = await _userManager.GetPhoneNumberAsync(user), | |||
TwoFactor = await _userManager.GetTwoFactorEnabledAsync(user), | |||
Logins = await _userManager.GetLoginsAsync(user), | |||
BrowserRemembered = await _signInManager.IsTwoFactorClientRememberedAsync(user) | |||
}; | |||
return View(model); | |||
} | |||
// | |||
// POST: /Manage/RemoveLogin | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> RemoveLogin(RemoveLoginViewModel account) | |||
{ | |||
ManageMessageId? message = ManageMessageId.Error; | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
var result = await _userManager.RemoveLoginAsync(user, account.LoginProvider, account.ProviderKey); | |||
if (result.Succeeded) | |||
{ | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
message = ManageMessageId.RemoveLoginSuccess; | |||
} | |||
} | |||
return RedirectToAction(nameof(ManageLogins), new { Message = message }); | |||
} | |||
// | |||
// GET: /Manage/AddPhoneNumber | |||
public IActionResult AddPhoneNumber() | |||
{ | |||
return View(); | |||
} | |||
// | |||
// POST: /Manage/AddPhoneNumber | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> AddPhoneNumber(AddPhoneNumberViewModel model) | |||
{ | |||
if (!ModelState.IsValid) | |||
{ | |||
return View(model); | |||
} | |||
// Generate the token and send it | |||
var user = await GetCurrentUserAsync(); | |||
if (user == null) | |||
{ | |||
return View("Error"); | |||
} | |||
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, model.PhoneNumber); | |||
await _smsSender.SendSmsAsync(model.PhoneNumber, "Your security code is: " + code); | |||
return RedirectToAction(nameof(VerifyPhoneNumber), new { PhoneNumber = model.PhoneNumber }); | |||
} | |||
// | |||
// POST: /Manage/EnableTwoFactorAuthentication | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> EnableTwoFactorAuthentication() | |||
{ | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
await _userManager.SetTwoFactorEnabledAsync(user, true); | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
_logger.LogInformation(1, "User enabled two-factor authentication."); | |||
} | |||
return RedirectToAction(nameof(Index), "Manage"); | |||
} | |||
// | |||
// POST: /Manage/DisableTwoFactorAuthentication | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> DisableTwoFactorAuthentication() | |||
{ | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
await _userManager.SetTwoFactorEnabledAsync(user, false); | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
_logger.LogInformation(2, "User disabled two-factor authentication."); | |||
} | |||
return RedirectToAction(nameof(Index), "Manage"); | |||
} | |||
// | |||
// GET: /Manage/VerifyPhoneNumber | |||
[HttpGet] | |||
public async Task<IActionResult> VerifyPhoneNumber(string phoneNumber) | |||
{ | |||
var user = await GetCurrentUserAsync(); | |||
if (user == null) | |||
{ | |||
return View("Error"); | |||
} | |||
var code = await _userManager.GenerateChangePhoneNumberTokenAsync(user, phoneNumber); | |||
// Send an SMS to verify the phone number | |||
return phoneNumber == null ? View("Error") : View(new VerifyPhoneNumberViewModel { PhoneNumber = phoneNumber }); | |||
} | |||
// | |||
// POST: /Manage/VerifyPhoneNumber | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> VerifyPhoneNumber(VerifyPhoneNumberViewModel model) | |||
{ | |||
if (!ModelState.IsValid) | |||
{ | |||
return View(model); | |||
} | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
var result = await _userManager.ChangePhoneNumberAsync(user, model.PhoneNumber, model.Code); | |||
if (result.Succeeded) | |||
{ | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AddPhoneSuccess }); | |||
} | |||
} | |||
// If we got this far, something failed, redisplay the form | |||
ModelState.AddModelError(string.Empty, "Failed to verify phone number"); | |||
return View(model); | |||
} | |||
// | |||
// POST: /Manage/RemovePhoneNumber | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> RemovePhoneNumber() | |||
{ | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
var result = await _userManager.SetPhoneNumberAsync(user, null); | |||
if (result.Succeeded) | |||
{ | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.RemovePhoneSuccess }); | |||
} | |||
} | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); | |||
} | |||
// | |||
// GET: /Manage/ChangePassword | |||
[HttpGet] | |||
public IActionResult ChangePassword() | |||
{ | |||
return View(); | |||
} | |||
// | |||
// POST: /Manage/ChangePassword | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> ChangePassword(ChangePasswordViewModel model) | |||
{ | |||
if (!ModelState.IsValid) | |||
{ | |||
return View(model); | |||
} | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
var result = await _userManager.ChangePasswordAsync(user, model.OldPassword, model.NewPassword); | |||
if (result.Succeeded) | |||
{ | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
_logger.LogInformation(3, "User changed their password successfully."); | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.ChangePasswordSuccess }); | |||
} | |||
AddErrors(result); | |||
return View(model); | |||
} | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); | |||
} | |||
// | |||
// GET: /Manage/SetPassword | |||
[HttpGet] | |||
public IActionResult SetPassword() | |||
{ | |||
return View(); | |||
} | |||
// | |||
// POST: /Manage/SetPassword | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public async Task<IActionResult> SetPassword(SetPasswordViewModel model) | |||
{ | |||
if (!ModelState.IsValid) | |||
{ | |||
return View(model); | |||
} | |||
var user = await GetCurrentUserAsync(); | |||
if (user != null) | |||
{ | |||
var result = await _userManager.AddPasswordAsync(user, model.NewPassword); | |||
if (result.Succeeded) | |||
{ | |||
await _signInManager.SignInAsync(user, isPersistent: false); | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.SetPasswordSuccess }); | |||
} | |||
AddErrors(result); | |||
return View(model); | |||
} | |||
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.Error }); | |||
} | |||
//GET: /Manage/ManageLogins | |||
[HttpGet] | |||
public async Task<IActionResult> ManageLogins(ManageMessageId? message = null) | |||
{ | |||
ViewData["StatusMessage"] = | |||
message == ManageMessageId.RemoveLoginSuccess ? "The external login was removed." | |||
: message == ManageMessageId.AddLoginSuccess ? "The external login was added." | |||
: message == ManageMessageId.Error ? "An error has occurred." | |||
: ""; | |||
var user = await GetCurrentUserAsync(); | |||
if (user == null) | |||
{ | |||
return View("Error"); | |||
} | |||
var userLogins = await _userManager.GetLoginsAsync(user); | |||
var otherLogins = _signInManager.GetExternalAuthenticationSchemes().Where(auth => userLogins.All(ul => auth.AuthenticationScheme != ul.LoginProvider)).ToList(); | |||
ViewData["ShowRemoveButton"] = user.PasswordHash != null || userLogins.Count > 1; | |||
return View(new ManageLoginsViewModel | |||
{ | |||
CurrentLogins = userLogins, | |||
OtherLogins = otherLogins | |||
}); | |||
} | |||
// | |||
// POST: /Manage/LinkLogin | |||
[HttpPost] | |||
[ValidateAntiForgeryToken] | |||
public IActionResult LinkLogin(string provider) | |||
{ | |||
// Request a redirect to the external login provider to link a login for the current user | |||
var redirectUrl = Url.Action("LinkLoginCallback", "Manage"); | |||
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User)); | |||
return Challenge(properties, provider); | |||
} | |||
// | |||
// GET: /Manage/LinkLoginCallback | |||
[HttpGet] | |||
public async Task<ActionResult> LinkLoginCallback() | |||
{ | |||
var user = await GetCurrentUserAsync(); | |||
if (user == null) | |||
{ | |||
return View("Error"); | |||
} | |||
var info = await _signInManager.GetExternalLoginInfoAsync(await _userManager.GetUserIdAsync(user)); | |||
if (info == null) | |||
{ | |||
return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error }); | |||
} | |||
var result = await _userManager.AddLoginAsync(user, info); | |||
var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error; | |||
return RedirectToAction(nameof(ManageLogins), new { Message = message }); | |||
} | |||
#region Helpers | |||
private void AddErrors(IdentityResult result) | |||
{ | |||
foreach (var error in result.Errors) | |||
{ | |||
ModelState.AddModelError(string.Empty, error.Description); | |||
} | |||
} | |||
public enum ManageMessageId | |||
{ | |||
AddPhoneSuccess, | |||
AddLoginSuccess, | |||
ChangePasswordSuccess, | |||
SetTwoFactorSuccess, | |||
SetPasswordSuccess, | |||
RemoveLoginSuccess, | |||
RemovePhoneSuccess, | |||
Error | |||
} | |||
private Task<ApplicationUser> GetCurrentUserAsync() | |||
{ | |||
return _userManager.GetUserAsync(HttpContext.User); | |||
} | |||
#endregion | |||
} | |||
} |
@ -0,0 +1,26 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore; | |||
using eShopOnContainers.Identity.Models; | |||
namespace eShopOnContainers.Identity.Data | |||
{ | |||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> | |||
{ | |||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) | |||
: base(options) | |||
{ | |||
} | |||
protected override void OnModelCreating(ModelBuilder builder) | |||
{ | |||
base.OnModelCreating(builder); | |||
// Customize the ASP.NET Identity model and override the defaults if needed. | |||
// For example, you can rename the ASP.NET Identity table names and more. | |||
// Add your customizations after calling base.OnModelCreating(builder); | |||
} | |||
} | |||
} |
@ -0,0 +1,7 @@ | |||
FROM microsoft/aspnetcore:1.0.1 | |||
ENTRYPOINT ["dotnet", "eShopOnContainers.Identity.dll"] | |||
ARG source=. | |||
WORKDIR /app | |||
ENV ASPNETCORE_URLS http://*:80 | |||
EXPOSE 80 | |||
COPY $source . |
@ -0,0 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class ExternalLoginConfirmationViewModel | |||
{ | |||
[Required] | |||
[EmailAddress] | |||
public string Email { get; set; } | |||
} | |||
} |
@ -0,0 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class ForgotPasswordViewModel | |||
{ | |||
[Required] | |||
[EmailAddress] | |||
public string Email { get; set; } | |||
} | |||
} |
@ -0,0 +1,22 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class LoginViewModel | |||
{ | |||
[Required] | |||
[EmailAddress] | |||
public string Email { get; set; } | |||
[Required] | |||
[DataType(DataType.Password)] | |||
public string Password { get; set; } | |||
[Display(Name = "Remember me?")] | |||
public bool RememberMe { get; set; } | |||
} | |||
} |
@ -0,0 +1,27 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class RegisterViewModel | |||
{ | |||
[Required] | |||
[EmailAddress] | |||
[Display(Name = "Email")] | |||
public string Email { get; set; } | |||
[Required] | |||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] | |||
[DataType(DataType.Password)] | |||
[Display(Name = "Password")] | |||
public string Password { get; set; } | |||
[DataType(DataType.Password)] | |||
[Display(Name = "Confirm password")] | |||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] | |||
public string ConfirmPassword { get; set; } | |||
} | |||
} |
@ -0,0 +1,27 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class ResetPasswordViewModel | |||
{ | |||
[Required] | |||
[EmailAddress] | |||
public string Email { get; set; } | |||
[Required] | |||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] | |||
[DataType(DataType.Password)] | |||
public string Password { get; set; } | |||
[DataType(DataType.Password)] | |||
[Display(Name = "Confirm password")] | |||
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] | |||
public string ConfirmPassword { get; set; } | |||
public string Code { get; set; } | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Mvc.Rendering; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class SendCodeViewModel | |||
{ | |||
public string SelectedProvider { get; set; } | |||
public ICollection<SelectListItem> Providers { get; set; } | |||
public string ReturnUrl { get; set; } | |||
public bool RememberMe { get; set; } | |||
} | |||
} |
@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.AccountViewModels | |||
{ | |||
public class VerifyCodeViewModel | |||
{ | |||
[Required] | |||
public string Provider { get; set; } | |||
[Required] | |||
public string Code { get; set; } | |||
public string ReturnUrl { get; set; } | |||
[Display(Name = "Remember this browser?")] | |||
public bool RememberBrowser { get; set; } | |||
[Display(Name = "Remember me?")] | |||
public bool RememberMe { get; set; } | |||
} | |||
} |
@ -0,0 +1,30 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | |||
using System.ComponentModel.DataAnnotations; | |||
namespace eShopOnContainers.Identity.Models | |||
{ | |||
// Add profile data for application users by adding properties to the ApplicationUser class | |||
public class ApplicationUser : IdentityUser | |||
{ | |||
public string CardNumber { get; set; } | |||
public string SecurityNumber { get; set; } | |||
public string Expiration { get; set; } | |||
public string CardHolderName { get; set; } | |||
public int CardType { get; set; } | |||
public string Street { get; set; } | |||
public string City { get; set; } | |||
public string State { get; set; } | |||
public string StateCode { get; set; } | |||
public string Country { get; set; } | |||
public string CountryCode { get; set; } | |||
public string ZipCode { get; set; } | |||
public double Latitude { get; set; } | |||
public double Longitude { get; set; } | |||
public string Name { get; set; } | |||
public string LastName { get; set; } | |||
} | |||
} |
@ -0,0 +1,16 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using System.Collections.Generic; | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class ConsentInputModel | |||
{ | |||
public string Button { get; set; } | |||
public IEnumerable<string> ScopesConsented { get; set; } | |||
public bool RememberConsent { get; set; } | |||
public string ReturnUrl { get; set; } | |||
} | |||
} |
@ -0,0 +1,57 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using IdentityServer4.Models; | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class ConsentViewModel : ConsentInputModel | |||
{ | |||
public ConsentViewModel(ConsentInputModel model, string returnUrl, AuthorizationRequest request, Client client, IEnumerable<Scope> scopes) | |||
{ | |||
RememberConsent = model?.RememberConsent ?? true; | |||
ScopesConsented = model?.ScopesConsented ?? Enumerable.Empty<string>(); | |||
ReturnUrl = returnUrl; | |||
ClientName = client.ClientName; | |||
ClientUrl = client.ClientUri; | |||
ClientLogoUrl = client.LogoUri; | |||
AllowRememberConsent = client.AllowRememberConsent; | |||
IdentityScopes = scopes.Where(x => x.Type == ScopeType.Identity).Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray(); | |||
ResourceScopes = scopes.Where(x => x.Type == ScopeType.Resource).Select(x => new ScopeViewModel(x, ScopesConsented.Contains(x.Name) || model == null)).ToArray(); | |||
} | |||
public string ClientName { get; set; } | |||
public string ClientUrl { get; set; } | |||
public string ClientLogoUrl { get; set; } | |||
public bool AllowRememberConsent { get; set; } | |||
public IEnumerable<ScopeViewModel> IdentityScopes { get; set; } | |||
public IEnumerable<ScopeViewModel> ResourceScopes { get; set; } | |||
} | |||
public class ScopeViewModel | |||
{ | |||
public ScopeViewModel(Scope scope, bool check) | |||
{ | |||
Name = scope.Name; | |||
DisplayName = scope.DisplayName; | |||
Description = scope.Description; | |||
Emphasize = scope.Emphasize; | |||
Required = scope.Required; | |||
Checked = check || scope.Required; | |||
} | |||
public string Name { get; set; } | |||
public string DisplayName { get; set; } | |||
public string Description { get; set; } | |||
public bool Emphasize { get; set; } | |||
public bool Required { get; set; } | |||
public bool Checked { get; set; } | |||
} | |||
} |
@ -0,0 +1,13 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using IdentityServer4.Models; | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class ErrorViewModel | |||
{ | |||
public ErrorMessage Error { get; set; } | |||
} | |||
} |
@ -0,0 +1,13 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class LoggedOutViewModel | |||
{ | |||
public string PostLogoutRedirectUri { get; set; } | |||
public string ClientName { get; set; } | |||
public string SignOutIframeUrl { get; set; } | |||
} | |||
} |
@ -0,0 +1,18 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using System.ComponentModel.DataAnnotations; | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class LoginInputModel | |||
{ | |||
[Required] | |||
public string Username { get; set; } | |||
[Required] | |||
public string Password { get; set; } | |||
public bool RememberLogin { get; set; } | |||
public string ReturnUrl { get; set; } | |||
} | |||
} |
@ -0,0 +1,20 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
using System.Collections.Generic; | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class LoginViewModel : LoginInputModel | |||
{ | |||
public bool EnableLocalLogin { get; set; } | |||
public IEnumerable<ExternalProvider> ExternalProviders { get; set; } | |||
} | |||
public class ExternalProvider | |||
{ | |||
public string DisplayName { get; set; } | |||
public string AuthenticationScheme { get; set; } | |||
} | |||
} |
@ -0,0 +1,11 @@ | |||
// Copyright (c) Brock Allen & Dominick Baier. All rights reserved. | |||
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. | |||
namespace IdentityServer4.Quickstart.UI.Models | |||
{ | |||
public class LogoutViewModel | |||
{ | |||
public string LogoutId { get; set; } | |||
} | |||
} |
@ -0,0 +1,16 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class AddPhoneNumberViewModel | |||
{ | |||
[Required] | |||
[Phone] | |||
[Display(Name = "Phone number")] | |||
public string PhoneNumber { get; set; } | |||
} | |||
} |
@ -0,0 +1,27 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class ChangePasswordViewModel | |||
{ | |||
[Required] | |||
[DataType(DataType.Password)] | |||
[Display(Name = "Current password")] | |||
public string OldPassword { get; set; } | |||
[Required] | |||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] | |||
[DataType(DataType.Password)] | |||
[Display(Name = "New password")] | |||
public string NewPassword { get; set; } | |||
[DataType(DataType.Password)] | |||
[Display(Name = "Confirm new password")] | |||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] | |||
public string ConfirmPassword { get; set; } | |||
} | |||
} |
@ -0,0 +1,15 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Mvc.Rendering; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class ConfigureTwoFactorViewModel | |||
{ | |||
public string SelectedProvider { get; set; } | |||
public ICollection<SelectListItem> Providers { get; set; } | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class FactorViewModel | |||
{ | |||
public string Purpose { get; set; } | |||
} | |||
} |
@ -0,0 +1,21 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Identity; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class IndexViewModel | |||
{ | |||
public bool HasPassword { get; set; } | |||
public IList<UserLoginInfo> Logins { get; set; } | |||
public string PhoneNumber { get; set; } | |||
public bool TwoFactor { get; set; } | |||
public bool BrowserRemembered { get; set; } | |||
} | |||
} |
@ -0,0 +1,16 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Http.Authentication; | |||
using Microsoft.AspNetCore.Identity; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class ManageLoginsViewModel | |||
{ | |||
public IList<UserLoginInfo> CurrentLogins { get; set; } | |||
public IList<AuthenticationDescription> OtherLogins { get; set; } | |||
} | |||
} |
@ -0,0 +1,14 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class RemoveLoginViewModel | |||
{ | |||
public string LoginProvider { get; set; } | |||
public string ProviderKey { get; set; } | |||
} | |||
} |
@ -0,0 +1,22 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class SetPasswordViewModel | |||
{ | |||
[Required] | |||
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)] | |||
[DataType(DataType.Password)] | |||
[Display(Name = "New password")] | |||
public string NewPassword { get; set; } | |||
[DataType(DataType.Password)] | |||
[Display(Name = "Confirm new password")] | |||
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] | |||
public string ConfirmPassword { get; set; } | |||
} | |||
} |
@ -0,0 +1,19 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.ComponentModel.DataAnnotations; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Models.ManageViewModels | |||
{ | |||
public class VerifyPhoneNumberViewModel | |||
{ | |||
[Required] | |||
public string Code { get; set; } | |||
[Required] | |||
[Phone] | |||
[Display(Name = "Phone number")] | |||
public string PhoneNumber { get; set; } | |||
} | |||
} |
@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Hosting; | |||
namespace eShopOnContainers.Identity | |||
{ | |||
public class Program | |||
{ | |||
public static void Main(string[] args) | |||
{ | |||
var host = new WebHostBuilder() | |||
.UseKestrel() | |||
//.UseUrls("http://localhost:5000") | |||
.UseContentRoot(Directory.GetCurrentDirectory()) | |||
.UseIISIntegration() | |||
.UseStartup<Startup>() | |||
.Build(); | |||
host.Run(); | |||
} | |||
} | |||
} |
@ -0,0 +1,28 @@ | |||
{ | |||
"iisSettings": { | |||
"windowsAuthentication": false, | |||
"anonymousAuthentication": true, | |||
"iisExpress": { | |||
"applicationUrl": "http://localhost:5000", | |||
"sslPort": 0 | |||
} | |||
}, | |||
"profiles": { | |||
"IIS Express": { | |||
"commandName": "IISExpress", | |||
"launchBrowser": true, | |||
"launchUrl": "http://localhost:5000", | |||
"environmentVariables": { | |||
"ASPNETCORE_ENVIRONMENT": "Development" | |||
} | |||
}, | |||
"eShopOnContainers.Identity": { | |||
"commandName": "Project", | |||
"launchBrowser": true, | |||
"launchUrl": "http://localhost:5000", | |||
"environmentVariables": { | |||
"ASPNETCORE_ENVIRONMENT": "Development" | |||
} | |||
} | |||
} | |||
} |
@ -0,0 +1,34 @@ | |||
using eShopOnContainers.Identity.Models; | |||
using Microsoft.AspNetCore.Identity; | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Services | |||
{ | |||
public class EFLoginService : ILoginService<ApplicationUser> | |||
{ | |||
UserManager<ApplicationUser> _userManager; | |||
SignInManager<ApplicationUser> _signInManager; | |||
public EFLoginService(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager) { | |||
_userManager = userManager; | |||
_signInManager = signInManager; | |||
} | |||
public async Task<ApplicationUser> FindByUsername(string user) | |||
{ | |||
return await _userManager.FindByNameAsync(user); | |||
} | |||
public async Task<bool> ValidateCredentials(ApplicationUser user, string password) | |||
{ | |||
return await _userManager.CheckPasswordAsync(user, password); | |||
} | |||
public Task SignIn(ApplicationUser user) { | |||
return _signInManager.SignInAsync(user, true); | |||
} | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Services | |||
{ | |||
public interface IEmailSender | |||
{ | |||
Task SendEmailAsync(string email, string subject, string message); | |||
} | |||
} |
@ -0,0 +1,14 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Services | |||
{ | |||
public interface ILoginService<T> | |||
{ | |||
Task<bool> ValidateCredentials(T user, string password); | |||
Task<T> FindByUsername(string user); | |||
Task SignIn(T user); | |||
} | |||
} |
@ -0,0 +1,12 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Services | |||
{ | |||
public interface ISmsSender | |||
{ | |||
Task SendSmsAsync(string number, string message); | |||
} | |||
} |
@ -0,0 +1,25 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
namespace eShopOnContainers.Identity.Services | |||
{ | |||
// This class is used by the application to send Email and SMS | |||
// when you turn on two-factor authentication in ASP.NET Identity. | |||
// For more details see this link http://go.microsoft.com/fwlink/?LinkID=532713 | |||
public class AuthMessageSender : IEmailSender, ISmsSender | |||
{ | |||
public Task SendEmailAsync(string email, string subject, string message) | |||
{ | |||
// Plug in your email service here to send an email. | |||
return Task.FromResult(0); | |||
} | |||
public Task SendSmsAsync(string number, string message) | |||
{ | |||
// Plug in your SMS service here to send a text message. | |||
return Task.FromResult(0); | |||
} | |||
} | |||
} |
@ -0,0 +1,112 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Threading.Tasks; | |||
using Microsoft.AspNetCore.Builder; | |||
using Microsoft.AspNetCore.Hosting; | |||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; | |||
using Microsoft.EntityFrameworkCore; | |||
using Microsoft.Extensions.Configuration; | |||
using Microsoft.Extensions.DependencyInjection; | |||
using Microsoft.Extensions.Logging; | |||
using eShopOnContainers.Identity.Data; | |||
using eShopOnContainers.Identity.Models; | |||
using eShopOnContainers.Identity.Services; | |||
using eShopOnContainers.Identity.Configuration; | |||
namespace eShopOnContainers.Identity | |||
{ | |||
public class Startup | |||
{ | |||
public Startup(IHostingEnvironment env) | |||
{ | |||
var builder = new ConfigurationBuilder() | |||
.SetBasePath(env.ContentRootPath) | |||
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) | |||
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); | |||
if (env.IsDevelopment()) | |||
{ | |||
// For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 | |||
builder.AddUserSecrets(); | |||
} | |||
builder.AddEnvironmentVariables(); | |||
Configuration = builder.Build(); | |||
} | |||
public IConfigurationRoot Configuration { get; } | |||
// This method gets called by the runtime. Use this method to add services to the container. | |||
public void ConfigureServices(IServiceCollection services) | |||
{ | |||
// Add framework services. | |||
services.AddDbContext<ApplicationDbContext>(options => | |||
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); | |||
services.AddIdentity<ApplicationUser, IdentityRole>() | |||
.AddEntityFrameworkStores<ApplicationDbContext>() | |||
.AddDefaultTokenProviders(); | |||
services.AddMvc(); | |||
services.AddTransient<IEmailSender, AuthMessageSender>(); | |||
services.AddTransient<ISmsSender, AuthMessageSender>(); | |||
services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>(); | |||
// Adds IdentityServer | |||
services.AddIdentityServer() | |||
.AddTemporarySigningCredential() | |||
.AddInMemoryScopes(Config.GetScopes()) | |||
.AddInMemoryClients(Config.GetClients()) | |||
.AddAspNetIdentity<ApplicationUser>(); | |||
//Configuration Settings: | |||
services.AddOptions(); | |||
services.Configure<ClientCallBackUrls>(Configuration.GetSection("ClientCallBackUrls")); | |||
} | |||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. | |||
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) | |||
{ | |||
loggerFactory.AddConsole(Configuration.GetSection("Logging")); | |||
loggerFactory.AddDebug(); | |||
if (env.IsDevelopment()) | |||
{ | |||
app.UseDeveloperExceptionPage(); | |||
app.UseDatabaseErrorPage(); | |||
app.UseBrowserLink(); | |||
} | |||
else | |||
{ | |||
app.UseExceptionHandler("/Home/Error"); | |||
} | |||
app.UseStaticFiles(); | |||
app.UseIdentity(); | |||
// Adds IdentityServer | |||
app.UseIdentityServer(); | |||
app.UseMvc(routes => | |||
{ | |||
routes.MapRoute( | |||
name: "default", | |||
template: "{controller=Home}/{action=Index}/{id?}"); | |||
}); | |||
try | |||
{ | |||
var context = (ApplicationDbContext)app | |||
.ApplicationServices.GetService(typeof(ApplicationDbContext)); | |||
using (context) | |||
{ | |||
context.Database.Migrate(); | |||
} | |||
} | |||
catch (Exception) { } | |||
} | |||
} | |||
} |
@ -0,0 +1,10 @@ | |||
@{ | |||
ViewData["Title"] = "Confirm Email"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<div> | |||
<p> | |||
Thank you for confirming your email. Please <a asp-controller="Account" asp-action="Login">Click here to Log in</a>. | |||
</p> | |||
</div> |
@ -0,0 +1,35 @@ | |||
@model ExternalLoginConfirmationViewModel | |||
@{ | |||
ViewData["Title"] = "Register"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<h3>Associate your @ViewData["LoginProvider"] account.</h3> | |||
<form asp-controller="Account" asp-action="ExternalLoginConfirmation" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal"> | |||
<h4>Association Form</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<p class="text-info"> | |||
You've successfully authenticated with <strong>@ViewData["LoginProvider"]</strong>. | |||
Please enter an email address for this site below and click the Register button to finish | |||
logging in. | |||
</p> | |||
<div class="form-group"> | |||
<label asp-for="Email" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Email" class="form-control" /> | |||
<span asp-validation-for="Email" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Register</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,8 @@ | |||
@{ | |||
ViewData["Title"] = "Login Failure"; | |||
} | |||
<header> | |||
<h2>@ViewData["Title"].</h2> | |||
<p class="text-danger">Unsuccessful login with service.</p> | |||
</header> |
@ -0,0 +1,31 @@ | |||
@model ForgotPasswordViewModel | |||
@{ | |||
ViewData["Title"] = "Forgot your password?"; | |||
} | |||
<h2>@ViewData["Title"]</h2> | |||
<p> | |||
For more information on how to enable reset password please see this <a href="http://go.microsoft.com/fwlink/?LinkID=532713">article</a>. | |||
</p> | |||
@*<form asp-controller="Account" asp-action="ForgotPassword" method="post" class="form-horizontal"> | |||
<h4>Enter your email.</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<div class="form-group"> | |||
<label asp-for="Email" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Email" class="form-control" /> | |||
<span asp-validation-for="Email" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Submit</button> | |||
</div> | |||
</div> | |||
</form>*@ | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,8 @@ | |||
@{ | |||
ViewData["Title"] = "Forgot Password Confirmation"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<p> | |||
Please check your email to reset your password. | |||
</p> |
@ -0,0 +1,8 @@ | |||
@{ | |||
ViewData["Title"] = "Locked out"; | |||
} | |||
<header> | |||
<h1 class="text-danger">Locked out.</h1> | |||
<p class="text-danger">This account has been locked out, please try again later.</p> | |||
</header> |
@ -0,0 +1,21 @@ | |||
@model IdentityServer4.Quickstart.UI.Models.LoggedOutViewModel | |||
<div class="page-header"> | |||
<h1> | |||
Logout | |||
<small>You are now logged out</small> | |||
</h1> | |||
@if (Model.PostLogoutRedirectUri != null) | |||
{ | |||
<div> | |||
Click <a href="@Model.PostLogoutRedirectUri">here</a> to return to the | |||
<span>@Model.ClientName</span> application. | |||
</div> | |||
} | |||
@if (Model.SignOutIframeUrl != null) | |||
{ | |||
<iframe style="display:none" width="0" height="0" class="signout" src="@Model.SignOutIframeUrl"></iframe> | |||
} | |||
</div> |
@ -0,0 +1,83 @@ | |||
@model IdentityServer4.Quickstart.UI.Models.LoginViewModel | |||
<div class="login-page"> | |||
<div class="page-header"> | |||
<h1>Login</h1> | |||
</div> | |||
@Html.Partial("_ValidationSummary") | |||
<div class="row"> | |||
@if (Model.EnableLocalLogin) | |||
{ | |||
<div class="col-sm-6"> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title">Local Login</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<form asp-route="Login"> | |||
<input type="hidden" asp-for="ReturnUrl" /> | |||
<fieldset> | |||
<div class="form-group"> | |||
<label asp-for="Username"></label> | |||
<input class="form-control" placeholder="Username" asp-for="Username" autofocus> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="Password"></label> | |||
<input type="password" class="form-control" placeholder="Password" asp-for="Password" autocomplete="off"> | |||
</div> | |||
<div class="form-group login-remember"> | |||
<label asp-for="RememberLogin"> | |||
<input asp-for="RememberLogin"> | |||
<strong>Remember My Login</strong> | |||
</label> | |||
</div> | |||
<div class="form-group"> | |||
<button class="btn btn-primary">Login</button> | |||
</div> | |||
</fieldset> | |||
</form> | |||
</div> | |||
</div> | |||
</div> | |||
} | |||
@if (Model.ExternalProviders.Any()) | |||
{ | |||
<div class="col-md-6 col-sm-6 external-providers"> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title">External Login</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<ul class="list-inline"> | |||
@foreach (var provider in Model.ExternalProviders) | |||
{ | |||
<li> | |||
<a class="btn btn-default" | |||
asp-action="ExternalLogin" | |||
asp-route-provider="@provider.AuthenticationScheme" | |||
asp-route-returnUrl="@Model.ReturnUrl"> | |||
@provider.DisplayName | |||
</a> | |||
</li> | |||
} | |||
</ul> | |||
</div> | |||
</div> | |||
</div> | |||
} | |||
@if (!Model.EnableLocalLogin && !Model.ExternalProviders.Any()) | |||
{ | |||
<div class="alert alert-warning"> | |||
<strong>Invalid login request</strong> | |||
There are no login schemes configured for this client. | |||
</div> | |||
} | |||
</div> | |||
</div> |
@ -0,0 +1,21 @@ | |||
@model IdentityServer4.Quickstart.UI.Models.LogoutViewModel | |||
<div class="logout-page"> | |||
<div class="page-header"> | |||
<h1>Logout</h1> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-6"> | |||
<p>Would you like to logout of IdentityServer?</p> | |||
<form asp-action="Logout"> | |||
<input type="hidden" name="logoutId" value="@Model.LogoutId" /> | |||
<fieldset> | |||
<div class="form-group"> | |||
<button class="btn btn-primary">Yes</button> | |||
</div> | |||
</fieldset> | |||
</form> | |||
</div> | |||
</div> | |||
</div> |
@ -0,0 +1,42 @@ | |||
@model RegisterViewModel | |||
@{ | |||
ViewData["Title"] = "Register"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Account" asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal"> | |||
<h4>Create a new account.</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<div class="form-group"> | |||
<label asp-for="Email" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Email" class="form-control" /> | |||
<span asp-validation-for="Email" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="Password" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Password" class="form-control" /> | |||
<span asp-validation-for="Password" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="ConfirmPassword" class="form-control" /> | |||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Register</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,43 @@ | |||
@model ResetPasswordViewModel | |||
@{ | |||
ViewData["Title"] = "Reset password"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Account" asp-action="ResetPassword" method="post" class="form-horizontal"> | |||
<h4>Reset your password.</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<input asp-for="Code" type="hidden" /> | |||
<div class="form-group"> | |||
<label asp-for="Email" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Email" class="form-control" /> | |||
<span asp-validation-for="Email" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="Password" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Password" class="form-control" /> | |||
<span asp-validation-for="Password" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="ConfirmPassword" class="form-control" /> | |||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Reset</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,8 @@ | |||
@{ | |||
ViewData["Title"] = "Reset password confirmation"; | |||
} | |||
<h1>@ViewData["Title"].</h1> | |||
<p> | |||
Your password has been reset. Please <a asp-controller="Account" asp-action="Login">Click here to log in</a>. | |||
</p> |
@ -0,0 +1,21 @@ | |||
@model SendCodeViewModel | |||
@{ | |||
ViewData["Title"] = "Send Verification Code"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Account" asp-action="SendCode" asp-route-returnurl="@Model.ReturnUrl" method="post" class="form-horizontal"> | |||
<input asp-for="RememberMe" type="hidden" /> | |||
<div class="row"> | |||
<div class="col-md-8"> | |||
Select Two-Factor Authentication Provider: | |||
<select asp-for="SelectedProvider" asp-items="Model.Providers"></select> | |||
<button type="submit" class="btn btn-default">Submit</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,38 @@ | |||
@model VerifyCodeViewModel | |||
@{ | |||
ViewData["Title"] = "Verify"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Account" asp-action="VerifyCode" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal"> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<input asp-for="Provider" type="hidden" /> | |||
<input asp-for="RememberMe" type="hidden" /> | |||
<h4>@ViewData["Status"]</h4> | |||
<hr /> | |||
<div class="form-group"> | |||
<label asp-for="Code" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Code" class="form-control" /> | |||
<span asp-validation-for="Code" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<div class="checkbox"> | |||
<input asp-for="RememberBrowser" /> | |||
<label asp-for="RememberBrowser"></label> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Submit</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,82 @@ | |||
@model IdentityServer4.Quickstart.UI.Models.ConsentViewModel | |||
<div class="page-consent"> | |||
<div class="row page-header"> | |||
<div class="col-sm-10"> | |||
@if (Model.ClientLogoUrl != null) | |||
{ | |||
<div class="client-logo"><img src="@Model.ClientLogoUrl"></div> | |||
} | |||
<h1> | |||
@Model.ClientName | |||
<small>is requesting your permission</small> | |||
</h1> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-8"> | |||
@Html.Partial("_ValidationSummary") | |||
<form asp-action="Index" class="consent-form"> | |||
<input type="hidden" asp-for="ReturnUrl" /> | |||
<div>Uncheck the permissions you do not wish to grant.</div> | |||
@if (Model.IdentityScopes.Any()) | |||
{ | |||
<div class="panel panel-default consent-buttons"> | |||
<div class="panel-heading"> | |||
<span class="glyphicon glyphicon-user"></span> | |||
Personal Information | |||
</div> | |||
<ul class="list-group"> | |||
@foreach (var scope in Model.IdentityScopes) | |||
{ | |||
@Html.Partial("_ScopeListItem", scope) | |||
} | |||
</ul> | |||
</div> | |||
} | |||
@if (Model.ResourceScopes.Any()) | |||
{ | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<span class="glyphicon glyphicon-tasks"></span> | |||
Application Access | |||
</div> | |||
<ul class="list-group"> | |||
@foreach (var scope in Model.ResourceScopes) | |||
{ | |||
@Html.Partial("_ScopeListItem", scope) | |||
} | |||
</ul> | |||
</div> | |||
} | |||
@if (Model.AllowRememberConsent) | |||
{ | |||
<div class="consent-remember"> | |||
<label> | |||
<input class="consent-scopecheck" asp-for="RememberConsent" /> | |||
<strong>Remember My Decision</strong> | |||
</label> | |||
</div> | |||
} | |||
<div class="consent-buttons"> | |||
<button name="button" value="yes" class="btn btn-primary" autofocus>Yes, Allow</button> | |||
<button name="button" value="no" class="btn">No, Do Not Allow</button> | |||
@if (Model.ClientUrl != null) | |||
{ | |||
<a class="pull-right btn btn-default" target="_blank" href="@Model.ClientUrl"> | |||
<span class="glyphicon glyphicon-info-sign"></span> | |||
<strong>@Model.ClientName</strong> | |||
</a> | |||
} | |||
</div> | |||
</form> | |||
</div> | |||
</div> | |||
</div> |
@ -0,0 +1,34 @@ | |||
@model IdentityServer4.Quickstart.UI.Models.ScopeViewModel | |||
<li class="list-group-item"> | |||
<label> | |||
<input class="consent-scopecheck" | |||
type="checkbox" | |||
name="ScopesConsented" | |||
id="scopes_@Model.Name" | |||
value="@Model.Name" | |||
checked="@Model.Checked" | |||
disabled="@Model.Required" /> | |||
@if (Model.Required) | |||
{ | |||
<input type="hidden" | |||
name="ScopesConsented" | |||
value="@Model.Name" /> | |||
} | |||
<strong>@Model.DisplayName</strong> | |||
@if (Model.Emphasize) | |||
{ | |||
<span class="glyphicon glyphicon-exclamation-sign"></span> | |||
} | |||
</label> | |||
@if (Model.Required) | |||
{ | |||
<span><em>(required)</em></span> | |||
} | |||
@if (Model.Description != null) | |||
{ | |||
<div class="consent-description"> | |||
<label for="scopes_@Model.Name">@Model.Description</label> | |||
</div> | |||
} | |||
</li> |
@ -0,0 +1,7 @@ | |||
@{ | |||
ViewData["Title"] = "About"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<h3>@ViewData["Message"]</h3> | |||
<p>Use this area to provide additional information.</p> |
@ -0,0 +1,17 @@ | |||
@{ | |||
ViewData["Title"] = "Contact"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<h3>@ViewData["Message"]</h3> | |||
<address> | |||
One Microsoft Way<br /> | |||
Redmond, WA 98052-6399<br /> | |||
<abbr title="Phone">P:</abbr> | |||
425.555.0100 | |||
</address> | |||
<address> | |||
<strong>Support:</strong> <a href="mailto:Support@example.com">Support@example.com</a><br /> | |||
<strong>Marketing:</strong> <a href="mailto:Marketing@example.com">Marketing@example.com</a> | |||
</address> |
@ -0,0 +1,30 @@ | |||
<div class="welcome-page"> | |||
<div class="row page-header"> | |||
<div class="col-sm-10"> | |||
<h1> | |||
<img class="icon" src="~/icon.jpg"> | |||
Welcome to IdentityServer4 | |||
@*<small>(build {version})</small>*@ | |||
</h1> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-8"> | |||
<p> | |||
IdentityServer publishes a | |||
<a href="~/.well-known/openid-configuration">discovery document</a> | |||
where you can find metadata and links to all the endpoints, key material, etc. | |||
</p> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-8"> | |||
<p> | |||
Here are links to the | |||
<a href="https://github.com/identityserver/IdentityServer4">source code repository</a>, | |||
and <a href="https://github.com/identityserver/IdentityServer4.Samples">ready to use samples</a>. | |||
</p> | |||
</div> | |||
</div> | |||
</div> |
@ -0,0 +1,27 @@ | |||
@model AddPhoneNumberViewModel | |||
@{ | |||
ViewData["Title"] = "Add Phone Number"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Manage" asp-action="AddPhoneNumber" method="post" class="form-horizontal"> | |||
<h4>Add a phone number.</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<div class="form-group"> | |||
<label asp-for="PhoneNumber" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="PhoneNumber" class="form-control" /> | |||
<span asp-validation-for="PhoneNumber" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Send verification code</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,42 @@ | |||
@model ChangePasswordViewModel | |||
@{ | |||
ViewData["Title"] = "Change Password"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Manage" asp-action="ChangePassword" method="post" class="form-horizontal"> | |||
<h4>Change Password Form</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<div class="form-group"> | |||
<label asp-for="OldPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="OldPassword" class="form-control" /> | |||
<span asp-validation-for="OldPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="NewPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="NewPassword" class="form-control" /> | |||
<span asp-validation-for="NewPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="ConfirmPassword" class="form-control" /> | |||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Change password</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,71 @@ | |||
@model IndexViewModel | |||
@{ | |||
ViewData["Title"] = "Manage your account"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<p class="text-success">@ViewData["StatusMessage"]</p> | |||
<div> | |||
<h4>Change your account settings</h4> | |||
<hr /> | |||
<dl class="dl-horizontal"> | |||
<dt>Password:</dt> | |||
<dd> | |||
@if (Model.HasPassword) | |||
{ | |||
<a asp-controller="Manage" asp-action="ChangePassword" class="btn-bracketed">Change</a> | |||
} | |||
else | |||
{ | |||
<a asp-controller="Manage" asp-action="SetPassword" class="btn-bracketed">Create</a> | |||
} | |||
</dd> | |||
<dt>External Logins:</dt> | |||
<dd> | |||
@Model.Logins.Count <a asp-controller="Manage" asp-action="ManageLogins" class="btn-bracketed">Manage</a> | |||
</dd> | |||
<dt>Phone Number:</dt> | |||
<dd> | |||
<p> | |||
Phone Numbers can used as a second factor of verification in two-factor authentication. | |||
See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a> | |||
for details on setting up this ASP.NET application to support two-factor authentication using SMS. | |||
</p> | |||
@*@(Model.PhoneNumber ?? "None") | |||
@if (Model.PhoneNumber != null) | |||
{ | |||
<br /> | |||
<a asp-controller="Manage" asp-action="AddPhoneNumber" class="btn-bracketed">Change</a> | |||
<form asp-controller="Manage" asp-action="RemovePhoneNumber" method="post"> | |||
[<button type="submit" class="btn-link">Remove</button>] | |||
</form> | |||
} | |||
else | |||
{ | |||
<a asp-controller="Manage" asp-action="AddPhoneNumber" class="btn-bracketed">Add</a> | |||
}*@ | |||
</dd> | |||
<dt>Two-Factor Authentication:</dt> | |||
<dd> | |||
<p> | |||
There are no two-factor authentication providers configured. See <a href="http://go.microsoft.com/fwlink/?LinkID=532713">this article</a> | |||
for setting up this application to support two-factor authentication. | |||
</p> | |||
@*@if (Model.TwoFactor) | |||
{ | |||
<form asp-controller="Manage" asp-action="DisableTwoFactorAuthentication" method="post" class="form-horizontal"> | |||
Enabled <button type="submit" class="btn-link btn-bracketed">Disable</button> | |||
</form> | |||
} | |||
else | |||
{ | |||
<form asp-controller="Manage" asp-action="EnableTwoFactorAuthentication" method="post" class="form-horizontal"> | |||
<button type="submit" class="btn-link btn-bracketed">Enable</button> Disabled | |||
</form> | |||
}*@ | |||
</dd> | |||
</dl> | |||
</div> |
@ -0,0 +1,54 @@ | |||
@model ManageLoginsViewModel | |||
@using Microsoft.AspNetCore.Http.Authentication | |||
@{ | |||
ViewData["Title"] = "Manage your external logins"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<p class="text-success">@ViewData["StatusMessage"]</p> | |||
@if (Model.CurrentLogins.Count > 0) | |||
{ | |||
<h4>Registered Logins</h4> | |||
<table class="table"> | |||
<tbody> | |||
@for (var index = 0; index < Model.CurrentLogins.Count; index++) | |||
{ | |||
<tr> | |||
<td>@Model.CurrentLogins[index].LoginProvider</td> | |||
<td> | |||
@if ((bool)ViewData["ShowRemoveButton"]) | |||
{ | |||
<form asp-controller="Manage" asp-action="RemoveLogin" method="post" class="form-horizontal"> | |||
<div> | |||
<input asp-for="@Model.CurrentLogins[index].LoginProvider" name="LoginProvider" type="hidden" /> | |||
<input asp-for="@Model.CurrentLogins[index].ProviderKey" name="ProviderKey" type="hidden" /> | |||
<input type="submit" class="btn btn-default" value="Remove" title="Remove this @Model.CurrentLogins[index].LoginProvider login from your account" /> | |||
</div> | |||
</form> | |||
} | |||
else | |||
{ | |||
@: | |||
} | |||
</td> | |||
</tr> | |||
} | |||
</tbody> | |||
</table> | |||
} | |||
@if (Model.OtherLogins.Count > 0) | |||
{ | |||
<h4>Add another service to log in.</h4> | |||
<hr /> | |||
<form asp-controller="Manage" asp-action="LinkLogin" method="post" class="form-horizontal"> | |||
<div id="socialLoginList"> | |||
<p> | |||
@foreach (var provider in Model.OtherLogins) | |||
{ | |||
<button type="submit" class="btn btn-default" name="provider" value="@provider.AuthenticationScheme" title="Log in using your @provider.DisplayName account">@provider.AuthenticationScheme</button> | |||
} | |||
</p> | |||
</div> | |||
</form> | |||
} |
@ -0,0 +1,38 @@ | |||
@model SetPasswordViewModel | |||
@{ | |||
ViewData["Title"] = "Set Password"; | |||
} | |||
<p class="text-info"> | |||
You do not have a local username/password for this site. Add a local | |||
account so you can log in without an external login. | |||
</p> | |||
<form asp-controller="Manage" asp-action="SetPassword" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal"> | |||
<h4>Set your password</h4> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<div class="form-group"> | |||
<label asp-for="NewPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="NewPassword" class="form-control" /> | |||
<span asp-validation-for="NewPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<label asp-for="ConfirmPassword" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="ConfirmPassword" class="form-control" /> | |||
<span asp-validation-for="ConfirmPassword" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Set password</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,30 @@ | |||
@model VerifyPhoneNumberViewModel | |||
@{ | |||
ViewData["Title"] = "Verify Phone Number"; | |||
} | |||
<h2>@ViewData["Title"].</h2> | |||
<form asp-controller="Manage" asp-action="VerifyPhoneNumber" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal"> | |||
<input asp-for="PhoneNumber" type="hidden" /> | |||
<h4>Add a phone number.</h4> | |||
<h5>@ViewData["Status"]</h5> | |||
<hr /> | |||
<div asp-validation-summary="All" class="text-danger"></div> | |||
<div class="form-group"> | |||
<label asp-for="Code" class="col-md-2 control-label"></label> | |||
<div class="col-md-10"> | |||
<input asp-for="Code" class="form-control" /> | |||
<span asp-validation-for="Code" class="text-danger"></span> | |||
</div> | |||
</div> | |||
<div class="form-group"> | |||
<div class="col-md-offset-2 col-md-10"> | |||
<button type="submit" class="btn btn-default">Submit</button> | |||
</div> | |||
</div> | |||
</form> | |||
@section Scripts { | |||
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); } | |||
} |
@ -0,0 +1,34 @@ | |||
@model IdentityServer4.Quickstart.UI.Models.ErrorViewModel | |||
@{ | |||
var error = Model?.Error?.Error; | |||
var request_id = Model?.Error?.RequestId; | |||
} | |||
<div class="error-page"> | |||
<div class="page-header"> | |||
<h1>Error</h1> | |||
</div> | |||
<div class="row"> | |||
<div class="col-sm-6"> | |||
<div class="alert alert-danger"> | |||
Sorry, there was an error | |||
@if (error != null) | |||
{ | |||
<strong> | |||
<em> | |||
: @error | |||
</em> | |||
</strong> | |||
} | |||
</div> | |||
@if (request_id != null) | |||
{ | |||
<div class="request-id">Request Id: @request_id</div> | |||
} | |||
</div> | |||
</div> | |||
</div> |
@ -0,0 +1,54 @@ | |||
<!DOCTYPE html> | |||
<html> | |||
<head> | |||
<meta charset="utf-8" /> | |||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |||
<title>IdentityServer4</title> | |||
<link rel="icon" type="image/x-icon" href="~/favicon.ico" /> | |||
<link rel="shortcut icon" type="image/x-icon" href="~/favicon.ico" /> | |||
<link rel="stylesheet" href="~/lib/bootstrap/css/bootstrap.css" /> | |||
<link rel="stylesheet" href="~/css/site.css" /> | |||
</head> | |||
<body> | |||
<div class="navbar navbar-inverse navbar-fixed-top"> | |||
<div class="container-fluid"> | |||
<div class="navbar-header"> | |||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> | |||
<span class="sr-only">Toggle navigation</span> | |||
<span class="icon-bar"></span> | |||
<span class="icon-bar"></span> | |||
<span class="icon-bar"></span> | |||
</button> | |||
<a href="~/"> | |||
<span class="navbar-brand"> | |||
<img src="~/icon.png" class="icon-banner"> | |||
IdentityServer4 | |||
</span> | |||
</a> | |||
</div> | |||
@if (User.Identity.IsAuthenticated) | |||
{ | |||
<ul class="nav navbar-nav"> | |||
<li class="dropdown"> | |||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">@User.Identity.Name <b class="caret"></b></a> | |||
<ul class="dropdown-menu"> | |||
<li><a asp-action="Logout" asp-controller="Account">Logout</a></li> | |||
@*<li class="divider"></li> | |||
<li><a asp-route="Login" asp-route-id="@ViewContext.HttpContext.Request.Query["id"]">Login With Different Account</a></li>*@ | |||
</ul> | |||
</li> | |||
</ul> | |||
} | |||
</div> | |||
</div> | |||
<div class="container body-content"> | |||
@RenderBody() | |||
</div> | |||
<script src="~/lib/jquery/jquery.js"></script> | |||
<script src="~/lib/bootstrap/js/bootstrap.js"></script> | |||
@RenderSection("scripts", required: false) | |||
</body> | |||
</html> |
@ -0,0 +1,26 @@ | |||
@using Microsoft.AspNetCore.Identity | |||
@using eShopOnContainers.Identity.Models | |||
@inject SignInManager<ApplicationUser> SignInManager | |||
@inject UserManager<ApplicationUser> UserManager | |||
@if (SignInManager.IsSignedIn(User)) | |||
{ | |||
<form asp-area="" asp-controller="Account" asp-action="LogOff" method="post" id="logoutForm" class="navbar-right"> | |||
<ul class="nav navbar-nav navbar-right"> | |||
<li> | |||
<a asp-area="" asp-controller="Manage" asp-action="Index" title="Manage">Hello @UserManager.GetUserName(User)!</a> | |||
</li> | |||
<li> | |||
<button type="submit" class="btn btn-link navbar-btn navbar-link">Log off</button> | |||
</li> | |||
</ul> | |||
</form> | |||
} | |||
else | |||
{ | |||
<ul class="nav navbar-nav navbar-right"> | |||
<li><a asp-area="" asp-controller="Account" asp-action="Register">Register</a></li> | |||
<li><a asp-area="" asp-controller="Account" asp-action="Login">Log in</a></li> | |||
</ul> | |||
} |
@ -0,0 +1,14 @@ | |||
<environment names="Development"> | |||
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script> | |||
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script> | |||
</environment> | |||
<environment names="Staging,Production"> | |||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.14.0/jquery.validate.min.js" | |||
asp-fallback-src="~/lib/jquery-validation/dist/jquery.validate.min.js" | |||
asp-fallback-test="window.jQuery && window.jQuery.validator"> | |||
</script> | |||
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js" | |||
asp-fallback-src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" | |||
asp-fallback-test="window.jQuery && window.jQuery.validator && window.jQuery.validator.unobtrusive"> | |||
</script> | |||
</environment> |
@ -0,0 +1,7 @@ | |||
@if (ViewContext.ModelState.IsValid == false) | |||
{ | |||
<div class="alert alert-danger"> | |||
<strong>Error</strong> | |||
<div asp-validation-summary="All" class="danger"></div> | |||
</div> | |||
} |
@ -0,0 +1 @@ | |||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers |
@ -0,0 +1,3 @@ | |||
@{ | |||
Layout = "_Layout"; | |||
} |
@ -0,0 +1,17 @@ | |||
{ | |||
"ConnectionStrings": { | |||
"DefaultConnection": "Server=identity.data;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word" | |||
//"DefaultConnection": "Server=127.0.0.1,5433;Database=aspnet-Microsoft.eShopOnContainers.WebMVC;User Id=sa;Password=Pass@word" | |||
}, | |||
"ClientsCallBackUrls": { | |||
"Spa": "http://localhost:5003" | |||
}, | |||
"Logging": { | |||
"IncludeScopes": false, | |||
"LogLevel": { | |||
"Default": "Debug", | |||
"System": "Information", | |||
"Microsoft": "Information" | |||
} | |||
} | |||
} |
@ -0,0 +1,10 @@ | |||
{ | |||
"name": "asp.net", | |||
"private": true, | |||
"dependencies": { | |||
"bootstrap": "3.3.6", | |||
"jquery": "2.2.0", | |||
"jquery-validation": "1.14.0", | |||
"jquery-validation-unobtrusive": "3.2.6" | |||
} | |||
} |
@ -0,0 +1,24 @@ | |||
// Configure bundling and minification for the project. | |||
// More info at https://go.microsoft.com/fwlink/?LinkId=808241 | |||
[ | |||
{ | |||
"outputFileName": "wwwroot/css/site.min.css", | |||
// An array of relative input file paths. Globbing patterns supported | |||
"inputFiles": [ | |||
"wwwroot/css/site.css" | |||
] | |||
}, | |||
{ | |||
"outputFileName": "wwwroot/js/site.min.js", | |||
"inputFiles": [ | |||
"wwwroot/js/site.js" | |||
], | |||
// Optionally specify minification options | |||
"minify": { | |||
"enabled": true, | |||
"renameLocals": true | |||
}, | |||
// Optinally generate .map file | |||
"sourceMap": false | |||
} | |||
] |
@ -0,0 +1,25 @@ | |||
version: '2' | |||
services: | |||
identity.service: | |||
image: eshop/identity | |||
build: | |||
context: . | |||
dockerfile: Dockerfile | |||
environment: | |||
- ConnectionString=Server=identity.data;Initial Catalog=CatalogData;User Id=sa;Password=Pass@word | |||
- Spa=http://localhost/5003 | |||
expose: | |||
- "80" | |||
ports: | |||
- "5101:80" | |||
depends_on: | |||
- identity.data | |||
identity.data: | |||
image: microsoft/mssql-server-linux | |||
environment: | |||
- SA_PASSWORD=Pass@word | |||
- ACCEPT_EULA=Y | |||
ports: | |||
- "5434:1433" |
@ -0,0 +1,23 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup> | |||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> | |||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> | |||
</PropertyGroup> | |||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> | |||
<PropertyGroup Label="Globals"> | |||
<ProjectGuid>a579e108-5445-403d-a407-339ac4d1611b</ProjectGuid> | |||
<RootNamespace>eShopOnContainers.Identity</RootNamespace> | |||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> | |||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> | |||
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion> | |||
</PropertyGroup> | |||
<PropertyGroup> | |||
<SchemaVersion>2.0</SchemaVersion> | |||
</PropertyGroup> | |||
<ItemGroup> | |||
<DnxInvisibleContent Include="bower.json" /> | |||
<DnxInvisibleContent Include=".bowerrc" /> | |||
</ItemGroup> | |||
<Import Project="$(VSToolsPath)\DotNet.Web\Microsoft.DotNet.Web.targets" Condition="'$(VSToolsPath)' != ''" /> | |||
</Project> |
@ -0,0 +1,105 @@ | |||
{ | |||
"userSecretsId": "aspnet-eShopOnContainers.Identity-90487118-103c-4ff0-b9da-e5e26f7ab0c5", | |||
"dependencies": { | |||
"Microsoft.NETCore.App": { | |||
"version": "1.0.1", | |||
"type": "platform" | |||
}, | |||
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0", | |||
"Microsoft.AspNetCore.Diagnostics": "1.0.0", | |||
"Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.0.0", | |||
"Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.0.0", | |||
"Microsoft.AspNetCore.Mvc": "1.0.1", | |||
"Microsoft.AspNetCore.Razor.Tools": { | |||
"version": "1.0.0-preview2-final", | |||
"type": "build" | |||
}, | |||
"Microsoft.AspNetCore.Routing": "1.0.1", | |||
"Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", | |||
"Microsoft.AspNetCore.Server.Kestrel": "1.0.1", | |||
"Microsoft.AspNetCore.StaticFiles": "1.0.0", | |||
"Microsoft.EntityFrameworkCore.SqlServer": "1.0.1", | |||
"Microsoft.EntityFrameworkCore.SqlServer.Design": { | |||
"version": "1.0.1", | |||
"type": "build" | |||
}, | |||
"Microsoft.EntityFrameworkCore.Tools": { | |||
"version": "1.0.0-preview2-final", | |||
"type": "build" | |||
}, | |||
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", | |||
"Microsoft.Extensions.Configuration.Json": "1.0.0", | |||
"Microsoft.Extensions.Configuration.UserSecrets": "1.0.0", | |||
"Microsoft.Extensions.Logging": "1.0.0", | |||
"Microsoft.Extensions.Logging.Console": "1.0.0", | |||
"Microsoft.Extensions.Logging.Debug": "1.0.0", | |||
"Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", | |||
"Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0", | |||
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": { | |||
"version": "1.0.0-preview2-final", | |||
"type": "build" | |||
}, | |||
"Microsoft.VisualStudio.Web.CodeGenerators.Mvc": { | |||
"version": "1.0.0-preview2-final", | |||
"type": "build" | |||
}, | |||
"IdentityServer4.AspNetIdentity": "1.0.0-rc3", | |||
"IdentityServer4.EntityFramework": "1.0.0-rc3" | |||
}, | |||
"tools": { | |||
"BundlerMinifier.Core": "2.0.238", | |||
"Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final", | |||
"Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final", | |||
"Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview2-final", | |||
"Microsoft.Extensions.SecretManager.Tools": "1.0.0-preview2-final", | |||
"Microsoft.VisualStudio.Web.CodeGeneration.Tools": { | |||
"version": "1.0.0-preview2-final", | |||
"imports": [ | |||
"portable-net45+win8" | |||
] | |||
} | |||
}, | |||
"frameworks": { | |||
"netcoreapp1.0": { | |||
"imports": [ | |||
"dotnet5.6", | |||
"portable-net45+win8" | |||
] | |||
} | |||
}, | |||
"buildOptions": { | |||
"emitEntryPoint": true, | |||
"preserveCompilationContext": true, | |||
"debugType": "portable" | |||
}, | |||
"runtimeOptions": { | |||
"configProperties": { | |||
"System.GC.Server": true | |||
} | |||
}, | |||
"publishOptions": { | |||
"include": [ | |||
"wwwroot", | |||
"Views", | |||
"Areas/**/Views", | |||
"appsettings.json", | |||
"web.config", | |||
"Dockerfile", | |||
"docker-compose.yml", | |||
".dockerignore" | |||
] | |||
}, | |||
"scripts": { | |||
"prepublish": [ | |||
"bower install", | |||
"dotnet bundle" | |||
], | |||
"postpublish": [ | |||
"dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" | |||
] | |||
} | |||
} |