├── .appveyor.yml ├── .gitignore ├── LICENSE ├── assets └── ServiceStack_IdentityServer_Interaction.png ├── build.cake ├── build.ps1 ├── docs ├── authenticate_impersonate.md ├── authenticate_impersonate_sample.md ├── authenticate_service.md ├── authenticate_service_sample.md └── authenticate_user_sample.md ├── readme.md └── src ├── IdentityServer3.Contrib.ServiceStack ├── ActAsUserGrantValidator.cs └── IdentityServer3.Contrib.ServiceStack.csproj ├── IdentityServer4.Contrib.ServiceStack ├── ActAsUserGrantValidator.cs └── IdentityServer4.Contrib.ServiceStack.csproj ├── ServiceStack.Auth.IdentityServer.sln ├── ServiceStack.Authentication.IdentityServer ├── AuthenticateResult.cs ├── Clients │ ├── ActAsUserGrantTokenClient.cs │ ├── AuthCodeClient.cs │ ├── DocumentDiscoveryClient.cs │ ├── IntrospectClient.cs │ ├── JsonWebKeyClient.cs │ ├── RefreshTokenClient.cs │ ├── ResourcePasswordTokenClient.cs │ ├── TokenCredentialsClient.cs │ └── UserInfoClient.cs ├── ConfigKeys.cs ├── DefaultClientSecretStore.cs ├── DocumentDiscoveryResult.cs ├── Enums │ ├── IdentityServerAuthProviderType.cs │ ├── IdentityServerOpenIdAuthorizationFlowType.cs │ └── TokenValidationResult.cs ├── Exceptions │ └── ConfigurationException.cs ├── Extensions │ ├── IdentityServerAuthProviderAppSettingsExtensions.cs │ └── RequestExtensions.cs ├── IdentityServerAuthFeature.cs ├── IdentityServerAuthTokens.cs ├── IdentityServerIdTokenValidator.cs ├── Interfaces │ ├── IActAsUserGrantTokenClient.cs │ ├── IAuthCodeClient.cs │ ├── IClientSecretStore.cs │ ├── IDocumentDiscoveryClient.cs │ ├── IIdentityServerAuthProviderSettings.cs │ ├── IIdentityServerIdTokenValidator.cs │ ├── IIdentityServerProvider.cs │ ├── IIntrospectClient.cs │ ├── IJsonWebKeyClient.cs │ ├── IRefreshTokenClient.cs │ ├── ITokenCredentialsClient.cs │ └── IUserInfoClient.cs ├── Providers │ ├── IdentityServerAuthProvider.cs │ ├── ImpersonationAuthProvider.cs │ ├── ResourcePasswordFlowAuthProvider.cs │ ├── ServiceAuthProvider.cs │ └── UserAuthProvider.cs ├── ServiceRegistration.cs ├── ServiceStack.Authentication.IdentityServer.csproj ├── TokenRefreshResult.cs └── TokenResult.cs ├── samples ├── IdentityServer3.SelfHost │ ├── App.config │ ├── IdentityServer3.SelfHost.csproj │ ├── Program.cs │ └── idsrv3test.pfx ├── IdentityServer4.SelfHost │ ├── Controllers │ │ ├── AccountController.cs │ │ └── HomeController.cs │ ├── IdentityServer4.SelfHost.csproj │ ├── Models │ │ ├── ErrorViewModel.cs │ │ ├── LoggedOutViewModel.cs │ │ ├── LoginInputModel.cs │ │ ├── LoginViewModel.cs │ │ └── LogoutViewModel.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── SecurityHeadersAttribute.cs │ ├── Views │ │ ├── Account │ │ │ ├── LoggedOut.cshtml │ │ │ └── Login.cshtml │ │ ├── Home │ │ │ └── Index.cshtml │ │ ├── Shared │ │ │ ├── Error.cshtml │ │ │ ├── _Layout.cshtml │ │ │ └── _ValidationSummary.cshtml │ │ ├── _ViewImports.cshtml │ │ └── _ViewStart.cshtml │ └── wwwroot │ │ ├── css │ │ ├── site.css │ │ ├── site.less │ │ └── site.min.css │ │ ├── favicon.ico │ │ ├── icon.jpg │ │ ├── icon.png │ │ ├── js │ │ └── signout-redirect.js │ │ └── lib │ │ ├── bootstrap │ │ ├── css │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ └── bootstrap.min.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ ├── bootstrap.js │ │ │ └── bootstrap.min.js │ │ └── jquery │ │ ├── jquery.js │ │ ├── jquery.min.js │ │ └── jquery.min.map ├── ImpersonateAuthProvider.ServiceStack.Api.SelfHost │ ├── App.config │ ├── AppHost.cs │ ├── ImpersonateAuthProvider.ServiceStack.Api.SelfHost.csproj │ ├── Program.cs │ ├── ServiceInterface │ │ ├── ExternalServices.cs │ │ └── MyServices.cs │ └── ServiceModel │ │ ├── External.cs │ │ └── Hello.cs ├── ImpersonateAuthProvider.ServiceStack.SelfHost │ ├── App.config │ ├── AppHost.cs │ ├── ImpersonateAuthProvider.ServiceStack.SelfHost.csproj │ ├── Program.cs │ ├── ServiceInterface │ │ ├── MyServices.cs │ │ └── SecureService.cs │ ├── ServiceModel │ │ ├── Hello.cs │ │ └── Secure.cs │ ├── Views │ │ ├── Hello.cshtml │ │ ├── Secure.cshtml │ │ └── Shared │ │ │ └── _Layout.cshtml │ └── default.cshtml ├── ServiceAuthProvider.ServiceStack.Api.SelfHost │ ├── App.config │ ├── AppHost.cs │ ├── Program.cs │ ├── ServiceAuthProvider.ServiceStack.Api.SelfHost.csproj │ ├── ServiceInterface │ │ ├── ExternalServices.cs │ │ └── MyServices.cs │ └── ServiceModel │ │ ├── External.cs │ │ └── Hello.cs ├── ServiceAuthProvider.ServiceStack.SelfHost │ ├── App.config │ ├── AppHost.cs │ ├── Program.cs │ ├── ServiceAuthProvider.ServiceStack.SelfHost.csproj │ ├── ServiceInterface │ │ ├── MyServices.cs │ │ └── SecureService.cs │ ├── ServiceModel │ │ ├── Hello.cs │ │ └── Secure.cs │ ├── Views │ │ ├── Hello.cshtml │ │ ├── Secure.cshtml │ │ └── Shared │ │ │ └── _Layout.cshtml │ └── default.cshtml ├── UserAuthProvider.ServiceStack.Core.SelfHost │ ├── AppHost.cs │ ├── Program.cs │ ├── Properties │ │ └── launchSettings.json │ ├── ServiceInterface │ │ └── MyServices.cs │ ├── ServiceModel │ │ └── Hello.cs │ ├── Startup.cs │ ├── UserAuthProvider.ServiceStack.Core.SelfHost.csproj │ ├── Views │ │ ├── Hello.cshtml │ │ └── Shared │ │ │ └── _Layout.cshtml │ ├── web.config │ └── wwwroot │ │ └── default.cshtml └── UserAuthProvider.ServiceStack.SelfHost │ ├── App.config │ ├── AppHost.cs │ ├── Program.cs │ ├── ServiceInterface │ └── MyServices.cs │ ├── ServiceModel │ └── Hello.cs │ ├── UserAuthProvider.ServiceStack.SelfHost.csproj │ ├── Views │ ├── Hello.cshtml │ └── Shared │ │ └── _Layout.cshtml │ └── default.cshtml └── test ├── IdentityServer3.Contrib.ServiceStack.Tests ├── ActAsUserGrantValidatorTests.cs └── IdentityServer3.Contrib.ServiceStack.Tests.csproj └── ServiceStack.Authentication.IdentityServer.Tests ├── IdentityServerAuthProviderAppSettingsExtensionsTests.cs ├── ServiceStack.Authentication.IdentityServer.Tests.csproj ├── TestIdentityServerAuthProviderSettings.cs └── UserAuthProviderTests.cs /.appveyor.yml: -------------------------------------------------------------------------------- 1 | #---------------------------------# 2 | # Build Script # 3 | #---------------------------------# 4 | build_script: 5 | - ps: .\build.ps1 -Target AppVeyor --settings_skipverification=true 6 | 7 | 8 | # Tests 9 | test: off 10 | 11 | #---------------------------------# 12 | # Branches to build # 13 | #---------------------------------# 14 | branches: 15 | # Whitelist 16 | only: 17 | - develop 18 | - master 19 | - /release/.*/ 20 | - /hotfix/.*/ 21 | 22 | #---------------------------------# 23 | # Build Cache # 24 | #---------------------------------# 25 | cache: 26 | - src\packages -> src\**\packages.config 27 | 28 | #---------------------------------# 29 | # environment configuration # 30 | #---------------------------------# 31 | 32 | # Build worker image (VM template) 33 | image: Visual Studio 2017 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | 24 | # Visual Studio 2015 cache/options directory 25 | .vs/ 26 | .idea/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | 84 | # Visual Studio profiler 85 | *.psess 86 | *.vsp 87 | *.vspx 88 | *.sap 89 | 90 | # TFS 2012 Local Workspace 91 | $tf/ 92 | 93 | # Guidance Automation Toolkit 94 | *.gpState 95 | 96 | # ReSharper is a .NET coding add-in 97 | _ReSharper*/ 98 | *.[Rr]e[Ss]harper 99 | *.DotSettings.user 100 | 101 | # JustCode is a .NET coding add-in 102 | .JustCode 103 | 104 | # TeamCity is a build add-in 105 | _TeamCity* 106 | 107 | # DotCover is a Code Coverage Tool 108 | *.dotCover 109 | 110 | # NCrunch 111 | _NCrunch_* 112 | .*crunch*.local.xml 113 | nCrunchTemp_* 114 | 115 | # MightyMoose 116 | *.mm.* 117 | AutoTest.Net/ 118 | 119 | # Web workbench (sass) 120 | .sass-cache/ 121 | 122 | # Installshield output folder 123 | [Ee]xpress/ 124 | 125 | # DocProject is a documentation generator add-in 126 | DocProject/buildhelp/ 127 | DocProject/Help/*.HxT 128 | DocProject/Help/*.HxC 129 | DocProject/Help/*.hhc 130 | DocProject/Help/*.hhk 131 | DocProject/Help/*.hhp 132 | DocProject/Help/Html2 133 | DocProject/Help/html 134 | 135 | # Click-Once directory 136 | publish/ 137 | 138 | # Publish Web Output 139 | *.[Pp]ublish.xml 140 | *.azurePubxml 141 | # TODO: Comment the next line if you want to checkin your web deploy settings 142 | # but database connection strings (with potential passwords) will be unencrypted 143 | *.pubxml 144 | *.publishproj 145 | 146 | # NuGet Packages 147 | *.nupkg 148 | # The packages folder can be ignored because of Package Restore 149 | **/packages/* 150 | # except build/, which is used as an MSBuild target. 151 | !**/packages/build/ 152 | # Uncomment if necessary however generally it will be regenerated when needed 153 | #!**/packages/repositories.config 154 | # NuGet v3's project.json files produces more ignoreable files 155 | *.nuget.props 156 | *.nuget.targets 157 | 158 | # Microsoft Azure Build Output 159 | csx/ 160 | *.build.csdef 161 | 162 | # Microsoft Azure Emulator 163 | ecf/ 164 | rcf/ 165 | 166 | # Microsoft Azure ApplicationInsights config file 167 | ApplicationInsights.config 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | ~$* 182 | *~ 183 | *.dbmdl 184 | *.dbproj.schemaview 185 | *.publishsettings 186 | node_modules/ 187 | orleans.codegen.cs 188 | 189 | # RIA/Silverlight projects 190 | Generated_Code/ 191 | 192 | # Backup & report files from converting an old project file 193 | # to a newer Visual Studio version. Backup files are not needed, 194 | # because we have git ;-) 195 | _UpgradeReport_Files/ 196 | Backup*/ 197 | UpgradeLog*.XML 198 | UpgradeLog*.htm 199 | 200 | # SQL Server files 201 | *.mdf 202 | *.ldf 203 | 204 | # Business Intelligence projects 205 | *.rdl.data 206 | *.bim.layout 207 | *.bim_*.settings 208 | 209 | # Microsoft Fakes 210 | FakesAssemblies/ 211 | 212 | # GhostDoc plugin setting file 213 | *.GhostDoc.xml 214 | 215 | # Node.js Tools for Visual Studio 216 | .ntvs_analysis.dat 217 | 218 | # Visual Studio 6 build log 219 | *.plg 220 | 221 | # Visual Studio 6 workspace options file 222 | *.opt 223 | 224 | # Visual Studio LightSwitch build output 225 | **/*.HTMLClient/GeneratedArtifacts 226 | **/*.DesktopClient/GeneratedArtifacts 227 | **/*.DesktopClient/ModelManifest.xml 228 | **/*.Server/GeneratedArtifacts 229 | **/*.Server/ModelManifest.xml 230 | _Pvt_Extensions 231 | 232 | # Paket dependency manager 233 | .paket/paket.exe 234 | 235 | # FAKE - F# Make 236 | .fake/ 237 | 238 | # VIM 239 | .swp 240 | /tools 241 | /cake.config 242 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/LICENSE -------------------------------------------------------------------------------- /assets/ServiceStack_IdentityServer_Interaction.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/assets/ServiceStack_IdentityServer_Interaction.png -------------------------------------------------------------------------------- /build.ps1: -------------------------------------------------------------------------------- 1 | ########################################################################## 2 | # This is the Cake bootstrapper script for PowerShell. 3 | # This file was downloaded from https://github.com/cake-build/resources 4 | # Feel free to change this file to fit your needs. 5 | ########################################################################## 6 | 7 | <# 8 | 9 | .SYNOPSIS 10 | This is a Powershell script to bootstrap a Cake build. 11 | 12 | .DESCRIPTION 13 | This Powershell script will download NuGet if missing, restore NuGet tools (including Cake) 14 | and execute your Cake build script with the parameters you provide. 15 | 16 | .PARAMETER Script 17 | The build script to execute. 18 | .PARAMETER Target 19 | The build script target to run. 20 | .PARAMETER Configuration 21 | The build configuration to use. 22 | .PARAMETER Verbosity 23 | Specifies the amount of information to be displayed. 24 | .PARAMETER ShowDescription 25 | Shows description about tasks. 26 | .PARAMETER DryRun 27 | Performs a dry run. 28 | .PARAMETER Experimental 29 | Uses the nightly builds of the Roslyn script engine. 30 | .PARAMETER Mono 31 | Uses the Mono Compiler rather than the Roslyn script engine. 32 | .PARAMETER SkipToolPackageRestore 33 | Skips restoring of packages. 34 | .PARAMETER ScriptArgs 35 | Remaining arguments are added here. 36 | 37 | .LINK 38 | https://cakebuild.net 39 | 40 | #> 41 | 42 | [CmdletBinding()] 43 | Param( 44 | [string]$Script = "build.cake", 45 | [string]$Target, 46 | [string]$Configuration, 47 | [ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")] 48 | [string]$Verbosity, 49 | [switch]$ShowDescription, 50 | [Alias("WhatIf", "Noop")] 51 | [switch]$DryRun, 52 | [switch]$Experimental, 53 | [switch]$Mono, 54 | [switch]$SkipToolPackageRestore, 55 | [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] 56 | [string[]]$ScriptArgs 57 | ) 58 | 59 | [Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null 60 | function MD5HashFile([string] $filePath) 61 | { 62 | if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf)) 63 | { 64 | return $null 65 | } 66 | 67 | [System.IO.Stream] $file = $null; 68 | [System.Security.Cryptography.MD5] $md5 = $null; 69 | try 70 | { 71 | $md5 = [System.Security.Cryptography.MD5]::Create() 72 | $file = [System.IO.File]::OpenRead($filePath) 73 | return [System.BitConverter]::ToString($md5.ComputeHash($file)) 74 | } 75 | finally 76 | { 77 | if ($file -ne $null) 78 | { 79 | $file.Dispose() 80 | } 81 | } 82 | } 83 | 84 | function GetProxyEnabledWebClient 85 | { 86 | $wc = New-Object System.Net.WebClient 87 | $proxy = [System.Net.WebRequest]::GetSystemWebProxy() 88 | $proxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials 89 | $wc.Proxy = $proxy 90 | return $wc 91 | } 92 | 93 | Write-Host "Preparing to run build script..." 94 | 95 | if(!$PSScriptRoot){ 96 | $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 97 | } 98 | 99 | $TOOLS_DIR = Join-Path $PSScriptRoot "tools" 100 | $ADDINS_DIR = Join-Path $TOOLS_DIR "Addins" 101 | $MODULES_DIR = Join-Path $TOOLS_DIR "Modules" 102 | $NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe" 103 | $CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe" 104 | $NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe" 105 | $PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config" 106 | $PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum" 107 | $ADDINS_PACKAGES_CONFIG = Join-Path $ADDINS_DIR "packages.config" 108 | $MODULES_PACKAGES_CONFIG = Join-Path $MODULES_DIR "packages.config" 109 | 110 | # Make sure tools folder exists 111 | if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) { 112 | Write-Verbose -Message "Creating tools directory..." 113 | New-Item -Path $TOOLS_DIR -Type directory | out-null 114 | } 115 | 116 | # Make sure that packages.config exist. 117 | if (!(Test-Path $PACKAGES_CONFIG)) { 118 | Write-Verbose -Message "Downloading packages.config..." 119 | try { 120 | $wc = GetProxyEnabledWebClient 121 | $wc.DownloadFile("https://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) 122 | } catch { 123 | Throw "Could not download packages.config." 124 | } 125 | } 126 | 127 | # Try find NuGet.exe in path if not exists 128 | if (!(Test-Path $NUGET_EXE)) { 129 | Write-Verbose -Message "Trying to find nuget.exe in PATH..." 130 | $existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_ -PathType Container) } 131 | $NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1 132 | if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) { 133 | Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)." 134 | $NUGET_EXE = $NUGET_EXE_IN_PATH.FullName 135 | } 136 | } 137 | 138 | # Try download NuGet.exe if not exists 139 | if (!(Test-Path $NUGET_EXE)) { 140 | Write-Verbose -Message "Downloading NuGet.exe..." 141 | try { 142 | $wc = GetProxyEnabledWebClient 143 | $wc.DownloadFile($NUGET_URL, $NUGET_EXE) 144 | } catch { 145 | Throw "Could not download NuGet.exe." 146 | } 147 | } 148 | 149 | # Save nuget.exe path to environment to be available to child processed 150 | $ENV:NUGET_EXE = $NUGET_EXE 151 | 152 | # Restore tools from NuGet? 153 | if(-Not $SkipToolPackageRestore.IsPresent) { 154 | Push-Location 155 | Set-Location $TOOLS_DIR 156 | 157 | # Check for changes in packages.config and remove installed tools if true. 158 | [string] $md5Hash = MD5HashFile($PACKAGES_CONFIG) 159 | if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or 160 | ($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) { 161 | Write-Verbose -Message "Missing or changed package.config hash..." 162 | Get-ChildItem -Exclude packages.config,nuget.exe,Cake.Bakery | 163 | Remove-Item -Recurse 164 | } 165 | 166 | Write-Verbose -Message "Restoring tools from NuGet..." 167 | $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`"" 168 | 169 | if ($LASTEXITCODE -ne 0) { 170 | Throw "An error occurred while restoring NuGet tools." 171 | } 172 | else 173 | { 174 | $md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII" 175 | } 176 | Write-Verbose -Message ($NuGetOutput | out-string) 177 | 178 | Pop-Location 179 | } 180 | 181 | # Restore addins from NuGet 182 | if (Test-Path $ADDINS_PACKAGES_CONFIG) { 183 | Push-Location 184 | Set-Location $ADDINS_DIR 185 | 186 | Write-Verbose -Message "Restoring addins from NuGet..." 187 | $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$ADDINS_DIR`"" 188 | 189 | if ($LASTEXITCODE -ne 0) { 190 | Throw "An error occurred while restoring NuGet addins." 191 | } 192 | 193 | Write-Verbose -Message ($NuGetOutput | out-string) 194 | 195 | Pop-Location 196 | } 197 | 198 | # Restore modules from NuGet 199 | if (Test-Path $MODULES_PACKAGES_CONFIG) { 200 | Push-Location 201 | Set-Location $MODULES_DIR 202 | 203 | Write-Verbose -Message "Restoring modules from NuGet..." 204 | $NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$MODULES_DIR`"" 205 | 206 | if ($LASTEXITCODE -ne 0) { 207 | Throw "An error occurred while restoring NuGet modules." 208 | } 209 | 210 | Write-Verbose -Message ($NuGetOutput | out-string) 211 | 212 | Pop-Location 213 | } 214 | 215 | # Make sure that Cake has been installed. 216 | if (!(Test-Path $CAKE_EXE)) { 217 | Throw "Could not find Cake.exe at $CAKE_EXE" 218 | } 219 | 220 | 221 | 222 | # Build Cake arguments 223 | $cakeArguments = @("$Script"); 224 | if ($Target) { $cakeArguments += "-target=$Target" } 225 | if ($Configuration) { $cakeArguments += "-configuration=$Configuration" } 226 | if ($Verbosity) { $cakeArguments += "-verbosity=$Verbosity" } 227 | if ($ShowDescription) { $cakeArguments += "-showdescription" } 228 | if ($DryRun) { $cakeArguments += "-dryrun" } 229 | if ($Experimental) { $cakeArguments += "-experimental" } 230 | if ($Mono) { $cakeArguments += "-mono" } 231 | $cakeArguments += $ScriptArgs 232 | 233 | # Start Cake 234 | Write-Host "Running build script..." 235 | &$CAKE_EXE $cakeArguments 236 | exit $LASTEXITCODE 237 | -------------------------------------------------------------------------------- /docs/authenticate_impersonate_sample.md: -------------------------------------------------------------------------------- 1 | # ImpersonateAuthProvider.ServiceStack.Api.SelfHost 2 | 3 | A demo project that provides a [ServiceStack](https://servicestack.net/) api instance that needs to impersonate a user that has logged into another application and is trying to access a secured api service requiring specific a specific role and specific permission. 4 | 5 | ## Overview 6 | This demo project bring uses the following plugins: 7 | * ServiceStack.Authentication.IdentityServer - a ServiceStack plugin that registers an AuthProvider that authenticates a user against an IdentityServer instance 8 | * IdentityServer3.Contrib.ServiceStack - an IdentityServer3 plugin that provides a custom token authentication endpoint that allows a ServiceStack instance to retrieve credentials from IdentityServer that impersonate a calling user. 9 | 10 | When the project starts, you should be presented with a simple ServiceStack web app with a link that redirects to a secure service in ServiceStack. When you select the link you should be redirected to the IdentityServer instance that prompts you for login details. Login using username "test@test.com" with password "password123". You should then be redirected back to the ServiceStack web app and have access to the secure service (with Authenticate attribute) which displays the secure message. A secure form is presented on the page that when text is entered in the field, a request is sent to a second ServiceStack service instance that will need to impersonate the calling user. 11 | 12 | ## Prerequisites 13 | The demo project must be run in conjunction with the following projects: 14 | * IdentityServer3.SelfHost - an IdentityServer instance configured to authenticate the ServiceStack Instances. 15 | * ImpersonateAuthProvider.ServiceStack.SelfHost - a ServiceStack razor-based Client App that provides the user interface and passes the Access Token that will be used to impersonate the user to the Api project -------------------------------------------------------------------------------- /docs/authenticate_service.md: -------------------------------------------------------------------------------- 1 | ## Authenticate as a Service - Quick Start 2 | ### ServiceStack Instance 3 | Install the package to your second Service Stack Instance: 4 | ```powershell 5 | PM> Install-Package ServiceStack.Authentication.IdentityServer 6 | ``` 7 | 8 | Add the following to your AppHost: 9 | ```csharp 10 | public class AppHost : AppSelfHostBase 11 | { 12 | public AppHost() : base("ServiceStack.SelfHost.Api", typeof (MyServices).Assembly) { } 13 | 14 | public override void Configure(Container container) 15 | { 16 | ... 17 | 18 | this.Plugins.Add(new IdentityServerAuthFeature 19 | { 20 | AuthProviderType = IdentityServerAuthProviderType.ServiceProvider, // Use the ServiceAuthProvider instead of the UserAuthProvider 21 | AuthRealm = "http://localhost:5000/", // The URL of the IdentityServer instance 22 | ClientId = "ServiceStack.SelfHost.Api", // The Client Identifier so that IdentityServer can identify the service 23 | ClientSecret = "6515372c-d1ab-457c-927a-13038007e977", // The Client Secret so that IdentityServer can authorize the service 24 | Scopes = "servicescope" // The Service must have a corresponding scope 25 | }); 26 | 27 | ... 28 | } 29 | } 30 | ``` 31 | 32 | To lock down a service so that the service has to be authenticated, again decorate it with the Authenticate Attribute. 33 | ```csharp 34 | public class SomeService : Service 35 | { 36 | [Authenticate(IdentityServerAuthProvider.Name)] 37 | public object Any() 38 | { 39 | ... 40 | } 41 | } 42 | ``` 43 | 44 | ### IdentityServer3 Instance 45 | Add the following Client to the Identity Server Client data store (example below is assuming IdentityServer In-Memory Clients is being used). 46 | ```csharp 47 | new Client 48 | { 49 | ClientName = "ServiceStack.SelfHost.Api", 50 | ClientId = "ServiceStack.SelfHost.Api", // The Client Identifier matching the AppSettings.SetClientId() call 51 | // in the ServiceStack AppHost Configure() method above 52 | Enabled = true, 53 | 54 | AccessTokenType = AccessTokenType.Jwt, // The AccessToken encryption type 55 | 56 | Flow = Flows.ClientCredentials, // Uses the Client Credentials flow 57 | 58 | ClientSecrets = new List<Secret> 59 | { 60 | new Secret("6515372c-d1ab-457c-927a-13038007e977".Sha256()) // The Client Secret matching AppSettings.SetClientSecret() call 61 | }, // in the ServiceStack Setup 62 | 63 | AllowedScopes = new List<Secret> // Ensure the scope for the new client is referenced. 64 | { 65 | "ServiceStack.Api.SelfHost" 66 | } 67 | } 68 | ``` 69 | 70 | Add the following Scope to the Identity Server Scope data store (example below is assuming IdentityServer In-Memory Scopes is being used). 71 | ```csharp 72 | new Scope 73 | { 74 | Enabled = true, 75 | Name = "ServiceStack.Api.SelfHost", // A Scope that matches the Client Id 76 | Type = ScopeType.Identity, 77 | 78 | ScopeSecrets = new List<Secret> // The Client Secret matching AppSettings.SetClientSecret() call 79 | { // in the ServiceStack Setup 80 | new Secret("6515372c-d1ab-457c-927a-13038007e977".Sha256()) 81 | } 82 | } 83 | ``` 84 | 85 | ### IdentityServer4 Instance 86 | Add the following Client to the Identity Server Client data store (example below is assuming IdentityServer In-Memory Clients is being used). 87 | new Client 88 | { 89 | ClientName = "ServiceStack.SelfHost.Api", 90 | ClientId = "ServiceStack.SelfHost.Api", // The Client Identifier matching the AppSettings.SetClientId() call 91 | // in the ServiceStack AppHost Configure() method above 92 | Enabled = true, 93 | 94 | AccessTokenType = AccessTokenType.Jwt, // The AccessToken encryption type 95 | 96 | AllowedGrantTypes = GrantTypes.ClientCredentials, // Uses the Client Credentials flow 97 | 98 | ClientSecrets = new List<Secret> 99 | { 100 | new Secret("6515372c-d1ab-457c-927a-13038007e977".Sha256()) // The Client Secret matching AppSettings.SetClientSecret() call 101 | }, // in the ServiceStack Setup 102 | 103 | AllowedScopes = new List<Secret> // Ensure the scope for the new client is referenced. 104 | { 105 | "ServiceStack.Api.SelfHost" 106 | } 107 | } 108 | ``` 109 | 110 | Add the following ApiResource to the Identity Server Api Resource data store (example below is assuming IdentityServer In-Memory Api Resource is being used). 111 | ```csharp 112 | new ApiResource 113 | { 114 | Name = "ServiceStack.SelfHost.Api", 115 | Enabled = true, 116 | ApiSecrets = new List 117 | { 118 | new Secret("6515372c-d1ab-457c-927a-13038007e977".Sha256()) 119 | }, 120 | Scopes = new List 121 | { 122 | new Scope("ServiceStack.SelfHost.Api") 123 | } 124 | } 125 | 126 | ## What just happened? 127 | Now when making a request to the exernal ServiceStack Instance the following should occur: 128 | 129 | * Attempting to access a ServiceStack Service with the Authenticate attribute forces a redirect to the IdentityServer Auth Provider (added by the *IdentityServerAuthFeature()* plugin). 130 | * The Auth Provider checks the current ServiceStack session for an *Access Token* issued by IdentityServer. 131 | * Having yet to be issued with an Access Token, the Auth Provider needs to request an Access Token from IdentityServer 132 | * The ServiceStack Auth Provider now uses the *Client ID* and the *Client Secret* to request an *Access Token* from IdentityServer using the [Token](https://identityserver.github.io/Documentation/docsv2/endpoints/token.html) endpoint. 133 | 134 | * *Token Endpoint* 135 | * Checks the Service Stack Instance *Client Id* and *Client Secret* are valid. 136 | * The IdentityServer Instance issues the *Access Token*. 137 | 138 | * The ServiceStack Auth Provider now validates the *Access Token* with IdentityServer using the [Token Introspection](https://identityserver.github.io/Documentation/docsv2/endpoints/introspection.html) endpoint. 139 | 140 | * *Introspection Endpoint* 141 | * Checks the Service Stack Instance *Client Id* and *Client Secret* are valid. 142 | * Checks the *Access Token* is valid. -------------------------------------------------------------------------------- /docs/authenticate_service_sample.md: -------------------------------------------------------------------------------- 1 | # ServiceAuthProvider.ServiceStack.Api.SelfHost 2 | 3 | A demo project that provides a [ServiceStack](https://servicestack.net/) api instance that needs to authenticate itself as a resource with an IdentityServer instance. 4 | 5 | ## Overview 6 | This demo project bring uses the Service Stack plugin ServiceStack.Authentication.IdentityServer that provides a ServiceStack AuthProvider that authenticates a user against an IdentityServer instance. 7 | 8 | When the project starts, you should be presented with a simple ServiceStack web app with a link that redirects to a secure service in ServiceStack. When you select the link you should be redirected to the IdentityServer instance that prompts you for login details. Login using username "test@test.com" with password "password123". You should then be redirected back to the ServiceStack web app and have access to the secure service (with Authenticate attribute) which displays the secure message. A secure form is presented on the page that when text is entered in the field, a request is sent to a second ServiceStack service instance that will need to authenticate itself with IdentityServer before being able to return a response. 9 | 10 | ## Prerequisites 11 | The demo project must be run in conjunction with the following projects: 12 | * IdentityServer3.SelfHost - an IdentityServer instance configured to authenticate the ServiceStack Instances. 13 | * ServiceAuthProvider.ServiceStack.SelfHost - a ServiceStack razor-based Client App that provides the user interface to the Api project -------------------------------------------------------------------------------- /docs/authenticate_user_sample.md: -------------------------------------------------------------------------------- 1 | # UserAuthProvider.ServiceStack.SelfHost 2 | 3 | A demo project that authenticates a [ServiceStack](https://servicestack.net/) razor-based Client App using [IdentityServer](https://identityserver.github.io/) 4 | 5 | ## Overview 6 | This demo project bring uses the Service Stack plugin ServiceStack.Authentication.IdentityServer that provides a ServiceStack AuthProvider that authenticates a user against an IdentityServer instance 7 | 8 | When the project starts, you should be presented with a simple ServiceStack web app with a link that redirects to a secure service in ServiceStack. When you select the link you should be redirected to the IdentityServer instance that prompts you for login details. Login using username "test@test.com" with password "password123". You should then be redirected back to the ServiceStack web app and have access to the secure service (with Authenticate attribute) which displays the secure message. 9 | 10 | ## Prerequisites 11 | The demo project must be run in conjunction with project IdentityServer3.SelfHost which is the IdentityServer instance configured to authenticate the ServiceStack Instance. -------------------------------------------------------------------------------- /src/IdentityServer3.Contrib.ServiceStack/ActAsUserGrantValidator.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer3.Contrib.ServiceStack 5 | { 6 | using System; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using Core; 10 | using Core.Services; 11 | using Core.Validation; 12 | 13 | /// 14 | /// Custom Grant Validator that takes an already valid access_token that has been created by another 15 | /// client and gets the subject (user) for that token. It then creates a new access token with the 16 | /// scopes that have been requested. 17 | /// 18 | public class ActAsUserGrantValidator : ICustomGrantValidator 19 | { 20 | public const string GrantTypeName = "act-as-user"; 21 | 22 | private readonly TokenValidator validator; 23 | 24 | /// Constructor 25 | /// Token Validator 26 | public ActAsUserGrantValidator(TokenValidator validator) 27 | { 28 | this.validator = validator; 29 | } 30 | 31 | /// Validates the Custom grant request 32 | /// 33 | /// 34 | public async Task ValidateAsync(ValidatedTokenRequest request) 35 | { 36 | var userAccessToken = request.Raw.Get("access_token"); 37 | var clientRefererToken = request.Raw.Get("client_referer"); 38 | if (string.IsNullOrWhiteSpace(userAccessToken)) 39 | { 40 | return new CustomGrantValidationResult(Constants.TokenErrors.InvalidRequest); 41 | } 42 | if (string.IsNullOrWhiteSpace(clientRefererToken)) 43 | { 44 | return new CustomGrantValidationResult(Constants.TokenErrors.InvalidRequest); 45 | } 46 | 47 | var result = await validator.ValidateAccessTokenAsync(userAccessToken).ConfigureAwait(false); 48 | if (result.IsError || result.Claims == null) 49 | { 50 | return new CustomGrantValidationResult(Constants.TokenErrors.InvalidRequest); 51 | } 52 | 53 | var subjectClaim = result.Claims.FirstOrDefault(x => x.Type == Constants.ClaimTypes.Subject); 54 | if (subjectClaim == null) 55 | { 56 | return new CustomGrantValidationResult(Constants.TokenErrors.InvalidRequest); 57 | } 58 | 59 | var client = result.Client; 60 | if (client == null || !client.RedirectUris.Any(x => x.IndexOf(clientRefererToken, StringComparison.OrdinalIgnoreCase) >= 0)) 61 | { 62 | return new CustomGrantValidationResult(Constants.TokenErrors.InvalidRequest); 63 | } 64 | 65 | return new CustomGrantValidationResult(subjectClaim.Value, "access_token"); 66 | } 67 | 68 | public string GrantType => GrantTypeName; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/IdentityServer3.Contrib.ServiceStack/IdentityServer3.Contrib.ServiceStack.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | An IdentityServer plugin for ServiceStack Authentication 5 | Copyright © 2016 6 | ServiceStack.IdentityServer.Provider 7 | true 8 | true 9 | https://www.mozilla.org/en-US/MPL/2.0/ 10 | https://identityserver.github.io/Documentation/assets/images/icons/IDserver_icon128.jpg 11 | https://github.com/wwwlicious/servicestack-authentication-identityserver 12 | ServiceStack;IdentityServer 13 | https://github.com/wwwlicious/servicestack-authentication-identityserver/releases 14 | Stuart Banks;Scott Mackay 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/IdentityServer4.Contrib.ServiceStack/ActAsUserGrantValidator.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.Contrib.ServiceStack 5 | { 6 | using System; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using IdentityModel; 10 | using Models; 11 | using Validation; 12 | 13 | public class ActAsUserGrantValidator : IExtensionGrantValidator 14 | { 15 | public const string GrantTypeName = "act-as-user"; 16 | 17 | private readonly ITokenValidator validator; 18 | 19 | /// Constructor 20 | /// Token Validator 21 | public ActAsUserGrantValidator(ITokenValidator validator) 22 | { 23 | this.validator = validator; 24 | } 25 | 26 | /// Validates the Custom grant request 27 | /// 28 | /// 29 | public async Task ValidateAsync(ExtensionGrantValidationContext context) 30 | { 31 | var userAccessToken = context.Request.Raw.Get("access_token"); 32 | var clientRefererToken = context.Request.Raw.Get("client_referer"); 33 | 34 | if (string.IsNullOrWhiteSpace(userAccessToken)) 35 | { 36 | context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest); 37 | return; 38 | } 39 | 40 | if (string.IsNullOrWhiteSpace(clientRefererToken)) 41 | { 42 | context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest); 43 | return; 44 | } 45 | 46 | var result = await validator.ValidateAccessTokenAsync(userAccessToken).ConfigureAwait(false); 47 | if (result.IsError || result.Claims == null) 48 | { 49 | context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest); 50 | return; 51 | } 52 | 53 | var subjectClaim = result.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject); 54 | if (subjectClaim == null) 55 | { 56 | context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest); 57 | return; 58 | } 59 | 60 | var client = result.Client; 61 | if (client == null || !client.RedirectUris.Any(x => x.IndexOf(clientRefererToken, StringComparison.OrdinalIgnoreCase) >= 0)) 62 | { 63 | context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest); 64 | } 65 | 66 | context.Result = new GrantValidationResult(subjectClaim.Value, "access_token"); 67 | } 68 | 69 | public string GrantType => GrantTypeName; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/IdentityServer4.Contrib.ServiceStack/IdentityServer4.Contrib.ServiceStack.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | An IdentityServer plugin for ServiceStack Authentication 5 | 4.0.0 6 | Stuart Banks;Scott Mackay 7 | netstandard2.0;net462 8 | 9 | true 10 | true 11 | https://www.mozilla.org/en-US/MPL/2.0/ 12 | ServiceStack;IdentityServer 13 | https://github.com/wwwlicious/servicestack-authentication-identityserver/releases 14 | https://identityserver.github.io/Documentation/assets/images/icons/IDserver_icon128.jpg 15 | https://github.com/wwwlicious/servicestack-authentication-identityserver 16 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/ServiceStack.Auth.IdentityServer.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26730.10 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E0581B00-91B9-44B8-953A-C78A9009AFFD}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityServer3.SelfHost", "samples\IdentityServer3.SelfHost\IdentityServer3.SelfHost.csproj", "{FD52FCE6-7084-4E25-BC03-C996FA1290CD}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServer4.SelfHost", "samples\IdentityServer4.SelfHost\IdentityServer4.SelfHost.csproj", "{83B85EDF-138C-4771-9937-6E78739774BA}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImpersonateAuthProvider.ServiceStack.SelfHost", "samples\ImpersonateAuthProvider.ServiceStack.SelfHost\ImpersonateAuthProvider.ServiceStack.SelfHost.csproj", "{D68485F5-897F-4CA2-B32A-3D7F373A1072}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImpersonateAuthProvider.ServiceStack.Api.SelfHost", "samples\ImpersonateAuthProvider.ServiceStack.Api.SelfHost\ImpersonateAuthProvider.ServiceStack.Api.SelfHost.csproj", "{3EC7759E-24AF-404C-BEFA-898FDCAD2E5A}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceAuthProvider.ServiceStack.Api.SelfHost", "samples\ServiceAuthProvider.ServiceStack.Api.SelfHost\ServiceAuthProvider.ServiceStack.Api.SelfHost.csproj", "{5B460989-7AFE-4ADD-A0B9-166F22B3953F}" 19 | EndProject 20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceAuthProvider.ServiceStack.SelfHost", "samples\ServiceAuthProvider.ServiceStack.SelfHost\ServiceAuthProvider.ServiceStack.SelfHost.csproj", "{24DB5141-F403-4784-BF20-3B7F5428BBA1}" 21 | EndProject 22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserAuthProvider.ServiceStack.SelfHost", "samples\UserAuthProvider.ServiceStack.SelfHost\UserAuthProvider.ServiceStack.SelfHost.csproj", "{CF36BF58-D08F-425A-9A6A-D0A86C506110}" 23 | EndProject 24 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityServer3.Contrib.ServiceStack", "IdentityServer3.Contrib.ServiceStack\IdentityServer3.Contrib.ServiceStack.csproj", "{E46B6750-64F6-4B18-837B-B1DF1FCC8786}" 25 | EndProject 26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServer4.Contrib.ServiceStack", "IdentityServer4.Contrib.ServiceStack\IdentityServer4.Contrib.ServiceStack.csproj", "{DF23A6F3-ACE2-499B-AA2E-E713D3468559}" 27 | EndProject 28 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityServer3.Contrib.ServiceStack.Tests", "test\IdentityServer3.Contrib.ServiceStack.Tests\IdentityServer3.Contrib.ServiceStack.Tests.csproj", "{1254F3F4-2F0C-48E3-8034-CA85F6030EC7}" 29 | EndProject 30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UserAuthProvider.ServiceStack.Core.SelfHost", "samples\UserAuthProvider.ServiceStack.Core.SelfHost\UserAuthProvider.ServiceStack.Core.SelfHost.csproj", "{7E50F023-0B67-4CFF-B31A-4112E4E68D0C}" 31 | EndProject 32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceStack.Authentication.IdentityServer", "ServiceStack.Authentication.IdentityServer\ServiceStack.Authentication.IdentityServer.csproj", "{D482DCC6-B1C0-454C-8A44-FAFAC1FCCD27}" 33 | EndProject 34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceStack.Authentication.IdentityServer.Tests", "test\ServiceStack.Authentication.IdentityServer.Tests\ServiceStack.Authentication.IdentityServer.Tests.csproj", "{D6309E21-EF77-4022-BF06-91B09739CFD9}" 35 | EndProject 36 | Global 37 | GlobalSection(NestedProjects) = preSolution 38 | {1254F3F4-2F0C-48E3-8034-CA85F6030EC7} = {E0581B00-91B9-44B8-953A-C78A9009AFFD} 39 | {D6309E21-EF77-4022-BF06-91B09739CFD9} = {E0581B00-91B9-44B8-953A-C78A9009AFFD} 40 | {FD52FCE6-7084-4E25-BC03-C996FA1290CD} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 41 | {83B85EDF-138C-4771-9937-6E78739774BA} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 42 | {3EC7759E-24AF-404C-BEFA-898FDCAD2E5A} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 43 | {D68485F5-897F-4CA2-B32A-3D7F373A1072} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 44 | {5B460989-7AFE-4ADD-A0B9-166F22B3953F} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 45 | {24DB5141-F403-4784-BF20-3B7F5428BBA1} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 46 | {7E50F023-0B67-4CFF-B31A-4112E4E68D0C} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 47 | {CF36BF58-D08F-425A-9A6A-D0A86C506110} = {05FEA8B8-73C7-4945-98EF-7CA53BB3B3E0} 48 | EndGlobalSection 49 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 50 | Debug|Any CPU = Debug|Any CPU 51 | Release|Any CPU = Release|Any CPU 52 | EndGlobalSection 53 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 54 | {E46B6750-64F6-4B18-837B-B1DF1FCC8786}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 55 | {E46B6750-64F6-4B18-837B-B1DF1FCC8786}.Debug|Any CPU.Build.0 = Debug|Any CPU 56 | {E46B6750-64F6-4B18-837B-B1DF1FCC8786}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {E46B6750-64F6-4B18-837B-B1DF1FCC8786}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {1254F3F4-2F0C-48E3-8034-CA85F6030EC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 59 | {1254F3F4-2F0C-48E3-8034-CA85F6030EC7}.Debug|Any CPU.Build.0 = Debug|Any CPU 60 | {1254F3F4-2F0C-48E3-8034-CA85F6030EC7}.Release|Any CPU.ActiveCfg = Release|Any CPU 61 | {1254F3F4-2F0C-48E3-8034-CA85F6030EC7}.Release|Any CPU.Build.0 = Release|Any CPU 62 | {FD52FCE6-7084-4E25-BC03-C996FA1290CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 63 | {FD52FCE6-7084-4E25-BC03-C996FA1290CD}.Debug|Any CPU.Build.0 = Debug|Any CPU 64 | {FD52FCE6-7084-4E25-BC03-C996FA1290CD}.Release|Any CPU.ActiveCfg = Release|Any CPU 65 | {FD52FCE6-7084-4E25-BC03-C996FA1290CD}.Release|Any CPU.Build.0 = Release|Any CPU 66 | {DF23A6F3-ACE2-499B-AA2E-E713D3468559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 67 | {DF23A6F3-ACE2-499B-AA2E-E713D3468559}.Debug|Any CPU.Build.0 = Debug|Any CPU 68 | {DF23A6F3-ACE2-499B-AA2E-E713D3468559}.Release|Any CPU.ActiveCfg = Release|Any CPU 69 | {DF23A6F3-ACE2-499B-AA2E-E713D3468559}.Release|Any CPU.Build.0 = Release|Any CPU 70 | {83B85EDF-138C-4771-9937-6E78739774BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 71 | {83B85EDF-138C-4771-9937-6E78739774BA}.Debug|Any CPU.Build.0 = Debug|Any CPU 72 | {83B85EDF-138C-4771-9937-6E78739774BA}.Release|Any CPU.ActiveCfg = Release|Any CPU 73 | {83B85EDF-138C-4771-9937-6E78739774BA}.Release|Any CPU.Build.0 = Release|Any CPU 74 | {3EC7759E-24AF-404C-BEFA-898FDCAD2E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 75 | {3EC7759E-24AF-404C-BEFA-898FDCAD2E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU 76 | {3EC7759E-24AF-404C-BEFA-898FDCAD2E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU 77 | {3EC7759E-24AF-404C-BEFA-898FDCAD2E5A}.Release|Any CPU.Build.0 = Release|Any CPU 78 | {D68485F5-897F-4CA2-B32A-3D7F373A1072}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 79 | {D68485F5-897F-4CA2-B32A-3D7F373A1072}.Debug|Any CPU.Build.0 = Debug|Any CPU 80 | {D68485F5-897F-4CA2-B32A-3D7F373A1072}.Release|Any CPU.ActiveCfg = Release|Any CPU 81 | {D68485F5-897F-4CA2-B32A-3D7F373A1072}.Release|Any CPU.Build.0 = Release|Any CPU 82 | {5B460989-7AFE-4ADD-A0B9-166F22B3953F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 83 | {5B460989-7AFE-4ADD-A0B9-166F22B3953F}.Debug|Any CPU.Build.0 = Debug|Any CPU 84 | {5B460989-7AFE-4ADD-A0B9-166F22B3953F}.Release|Any CPU.ActiveCfg = Release|Any CPU 85 | {5B460989-7AFE-4ADD-A0B9-166F22B3953F}.Release|Any CPU.Build.0 = Release|Any CPU 86 | {24DB5141-F403-4784-BF20-3B7F5428BBA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 87 | {24DB5141-F403-4784-BF20-3B7F5428BBA1}.Debug|Any CPU.Build.0 = Debug|Any CPU 88 | {24DB5141-F403-4784-BF20-3B7F5428BBA1}.Release|Any CPU.ActiveCfg = Release|Any CPU 89 | {24DB5141-F403-4784-BF20-3B7F5428BBA1}.Release|Any CPU.Build.0 = Release|Any CPU 90 | {D482DCC6-B1C0-454C-8A44-FAFAC1FCCD27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 91 | {D482DCC6-B1C0-454C-8A44-FAFAC1FCCD27}.Debug|Any CPU.Build.0 = Debug|Any CPU 92 | {D482DCC6-B1C0-454C-8A44-FAFAC1FCCD27}.Release|Any CPU.ActiveCfg = Release|Any CPU 93 | {D482DCC6-B1C0-454C-8A44-FAFAC1FCCD27}.Release|Any CPU.Build.0 = Release|Any CPU 94 | {D6309E21-EF77-4022-BF06-91B09739CFD9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 95 | {D6309E21-EF77-4022-BF06-91B09739CFD9}.Debug|Any CPU.Build.0 = Debug|Any CPU 96 | {D6309E21-EF77-4022-BF06-91B09739CFD9}.Release|Any CPU.ActiveCfg = Release|Any CPU 97 | {D6309E21-EF77-4022-BF06-91B09739CFD9}.Release|Any CPU.Build.0 = Release|Any CPU 98 | {7E50F023-0B67-4CFF-B31A-4112E4E68D0C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 99 | {7E50F023-0B67-4CFF-B31A-4112E4E68D0C}.Debug|Any CPU.Build.0 = Debug|Any CPU 100 | {7E50F023-0B67-4CFF-B31A-4112E4E68D0C}.Release|Any CPU.ActiveCfg = Release|Any CPU 101 | {7E50F023-0B67-4CFF-B31A-4112E4E68D0C}.Release|Any CPU.Build.0 = Release|Any CPU 102 | {CF36BF58-D08F-425A-9A6A-D0A86C506110}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 103 | {CF36BF58-D08F-425A-9A6A-D0A86C506110}.Debug|Any CPU.Build.0 = Debug|Any CPU 104 | {CF36BF58-D08F-425A-9A6A-D0A86C506110}.Release|Any CPU.ActiveCfg = Release|Any CPU 105 | {CF36BF58-D08F-425A-9A6A-D0A86C506110}.Release|Any CPU.Build.0 = Release|Any CPU 106 | EndGlobalSection 107 | EndGlobal 108 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/AuthenticateResult.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | public class AuthenticateResult 7 | { 8 | public string Code { get; set; } 9 | 10 | public string IdToken { get; set; } 11 | 12 | public bool IsEmpty => string.IsNullOrEmpty(Code) || string.IsNullOrEmpty(IdToken); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/ActAsUserGrantTokenClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | 9 | using IdentityModel.Client; 10 | using Interfaces; 11 | using Logging; 12 | 13 | class ActAsUserGrantTokenClient : IActAsUserGrantTokenClient 14 | { 15 | private static readonly ILog Log = LogManager.GetLogger(typeof(ActAsUserGrantTokenClient)); 16 | 17 | private readonly IIdentityServerAuthProviderSettings appSettings; 18 | 19 | public ActAsUserGrantTokenClient(IIdentityServerAuthProviderSettings settings) 20 | { 21 | this.appSettings = settings; 22 | } 23 | 24 | public async Task RequestCode(string accessToken, string accessTokenUrl) 25 | { 26 | var client = new TokenClient(appSettings.RequestTokenUrl, appSettings.ClientId, appSettings.ClientSecret); 27 | 28 | var response = await client.RequestCustomGrantAsync("act-as-user", appSettings.Scopes, new Dictionary 29 | { 30 | { "access_token", accessToken }, 31 | { "client_referer", accessTokenUrl } 32 | }).ConfigureAwait(false); 33 | 34 | if (response.IsError) 35 | { 36 | Log.Error($"An error occurred while validating the access token - {response.Error}"); 37 | } 38 | 39 | return response.AccessToken; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/AuthCodeClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | using IdentityModel.Client; 9 | using Interfaces; 10 | 11 | public class AuthCodeClient : IAuthCodeClient 12 | { 13 | private readonly IIdentityServerAuthProviderSettings settings; 14 | 15 | public AuthCodeClient(IIdentityServerAuthProviderSettings settings) 16 | { 17 | this.settings = settings; 18 | } 19 | 20 | public async Task RequestCode(string code, string callbackUrl) 21 | { 22 | var client = new TokenClient(settings.RequestTokenUrl, settings.ClientId, settings.ClientSecret); 23 | var result = await client.RequestAsync(new Dictionary 24 | { 25 | {"grant_type", "authorization_code"}, 26 | {"code", code}, 27 | {"redirect_uri", callbackUrl} 28 | }).ConfigureAwait(false); 29 | 30 | if (result.IsError) 31 | { 32 | return new TokenRefreshResult(); 33 | } 34 | 35 | return new TokenRefreshResult { AccessToken = result.AccessToken, RefreshToken = result.RefreshToken }; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/DocumentDiscoveryClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | using Interfaces; 10 | using Logging; 11 | 12 | internal class DocumentDiscoveryClient : IDocumentDiscoveryClient 13 | { 14 | private static readonly ILog Log = LogManager.GetLogger(typeof(DocumentDiscoveryClient)); 15 | 16 | private readonly IIdentityServerAuthProviderSettings appSettings; 17 | 18 | public DocumentDiscoveryClient(IIdentityServerAuthProviderSettings settings) 19 | { 20 | this.appSettings = settings; 21 | } 22 | 23 | public async Task GetAsync(string endpoint) 24 | { 25 | IJsonServiceClient client = new JsonServiceClient(appSettings.AuthRealm); 26 | 27 | string document; 28 | try 29 | { 30 | document = await client.GetAsync(endpoint) 31 | .ConfigureAwait(false); 32 | } 33 | catch (AggregateException exception) 34 | { 35 | foreach (var ex in exception.InnerExceptions) 36 | { 37 | Log.Error($"Error occurred requesting document data from {endpoint}", ex); 38 | } 39 | return null; 40 | } 41 | 42 | var configuration = new Microsoft.IdentityModel.Protocols.OpenIdConnect.OpenIdConnectConfiguration(document); 43 | return new DocumentDiscoveryResult 44 | { 45 | AuthorizeUrl = configuration.AuthorizationEndpoint, 46 | IntrospectUrl = GetStringValue(document, "introspection_endpoint"), 47 | UserInfoUrl = configuration.UserInfoEndpoint, 48 | TokenUrl = configuration.TokenEndpoint, 49 | JwksUrl = configuration.JwksUri 50 | }; 51 | } 52 | 53 | private static string GetStringValue(string document, string name) 54 | { 55 | var dictionary = document.FromJson>(); 56 | object obj; 57 | if (dictionary.TryGetValue(name, out obj)) 58 | { 59 | return obj as string; 60 | } 61 | return null; 62 | } 63 | 64 | private static string GetStringValue(Dictionary document, string name) 65 | { 66 | object obj; 67 | if (document.TryGetValue(name, out obj)) 68 | { 69 | return obj as string; 70 | } 71 | return null; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/IntrospectClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using Enums; 7 | using IdentityModel.Client; 8 | using Interfaces; 9 | using Logging; 10 | using System.Threading.Tasks; 11 | 12 | internal class IntrospectClient : IIntrospectClient 13 | { 14 | private static readonly ILog Log = LogManager.GetLogger(typeof(IntrospectClient)); 15 | 16 | private readonly IIdentityServerAuthProviderSettings appSettings; 17 | 18 | public IntrospectClient(IIdentityServerAuthProviderSettings appSettings) 19 | { 20 | this.appSettings = appSettings; 21 | } 22 | 23 | public async Task IsValidToken(string accessToken) 24 | { 25 | var client = new IntrospectionClient(appSettings.IntrospectUrl); 26 | var result = await client.SendAsync(new IntrospectionRequest 27 | { 28 | Token = accessToken, 29 | 30 | ClientId = appSettings.ClientId, 31 | ClientSecret = appSettings.ClientSecret 32 | }).ConfigureAwait(false); 33 | 34 | if (result.IsError) 35 | { 36 | Log.Error($"An error occurred while validating the access token - {result.Error}"); 37 | return TokenValidationResult.Error; 38 | } 39 | 40 | if (!result.IsActive) 41 | { 42 | Log.Error("Access token is not active"); 43 | return TokenValidationResult.Expired; 44 | } 45 | 46 | return TokenValidationResult.Success; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/JsonWebKeyClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | using Interfaces; 10 | using Logging; 11 | 12 | internal class JsonWebKeyClient : IJsonWebKeyClient 13 | { 14 | private static readonly ILog Log = LogManager.GetLogger(typeof(JsonWebKeyClient)); 15 | 16 | private readonly IIdentityServerAuthProviderSettings appSettings; 17 | 18 | public JsonWebKeyClient(IIdentityServerAuthProviderSettings settings) 19 | { 20 | appSettings = settings; 21 | } 22 | 23 | public async Task> GetAsync() 24 | { 25 | var httpClient = new JsonServiceClient(); 26 | 27 | string document; 28 | 29 | try 30 | { 31 | document = await httpClient.GetAsync(appSettings.JwksUrl) 32 | .ConfigureAwait(false); 33 | } 34 | catch (AggregateException exception) 35 | { 36 | foreach (var ex in exception.InnerExceptions) 37 | { 38 | Log.Error($"Error occurred requesting json web key set from {appSettings.JwksUrl}", ex); 39 | } 40 | return null; 41 | } 42 | 43 | 44 | var webKeySet = new Microsoft.IdentityModel.Tokens.JsonWebKeySet(document); 45 | return webKeySet.GetSigningKeys(); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/RefreshTokenClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace ServiceStack.Authentication.IdentityServer.Clients 9 | { 10 | using IdentityModel.Client; 11 | using Interfaces; 12 | using Logging; 13 | 14 | internal class RefreshTokenClient : IRefreshTokenClient 15 | { 16 | private static readonly ILog Log = LogManager.GetLogger(typeof(RefreshTokenClient)); 17 | 18 | private readonly IIdentityServerAuthProviderSettings appSettings; 19 | 20 | public RefreshTokenClient(IIdentityServerAuthProviderSettings appSettings) 21 | { 22 | this.appSettings = appSettings; 23 | } 24 | 25 | public async Task RefreshToken(string refreshToken) 26 | { 27 | var client = new TokenClient(appSettings.RequestTokenUrl, appSettings.ClientId, appSettings.ClientSecret); 28 | var result = await client.RequestAsync(new Dictionary 29 | { 30 | {"grant_type", "refresh_token"}, 31 | {"refresh_token", refreshToken} 32 | }).ConfigureAwait(false); 33 | 34 | if (result.IsError) 35 | { 36 | Log.Error($"An error occurred while refreshing the access token - {result.Error}"); 37 | return new TokenRefreshResult(); 38 | } 39 | 40 | return new TokenRefreshResult 41 | { 42 | AccessToken = result.AccessToken, 43 | RefreshToken = result.RefreshToken, 44 | ExpiresAt = DateTime.UtcNow.AddSeconds(result.ExpiresIn) 45 | }; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/ResourcePasswordTokenClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System.Threading.Tasks; 7 | using IdentityModel.Client; 8 | using Interfaces; 9 | using Logging; 10 | 11 | public class ResourcePasswordTokenClient : ITokenCredentialsClient 12 | { 13 | private static readonly ILog Log = LogManager.GetLogger(typeof(ResourcePasswordTokenClient)); 14 | 15 | private readonly IIdentityServerAuthProviderSettings appSettings; 16 | 17 | public ResourcePasswordTokenClient(IIdentityServerAuthProviderSettings settings) 18 | { 19 | this.appSettings = settings; 20 | } 21 | 22 | public async Task RequestToken() 23 | { 24 | var client = new TokenClient(appSettings.RequestTokenUrl, appSettings.ClientId, appSettings.ClientSecret); 25 | client.AuthenticationStyle = AuthenticationStyle.PostValues; 26 | var result = await client.RequestResourceOwnerPasswordAsync(userName: appSettings.Username, password: appSettings.Password, scope: appSettings.Scopes).ConfigureAwait(false); 27 | 28 | if (result.IsError) 29 | { 30 | Log.Error($"An error occurred while requesting the access token - {result.Error}"); 31 | return new TokenResult(); 32 | } 33 | 34 | return new TokenResult { AccessToken = result.AccessToken }; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/TokenCredentialsClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System.Threading.Tasks; 7 | using IdentityModel.Client; 8 | using Interfaces; 9 | using Logging; 10 | 11 | public class TokenCredentialsClient : ITokenCredentialsClient 12 | { 13 | private static readonly ILog Log = LogManager.GetLogger(typeof(TokenCredentialsClient)); 14 | 15 | private readonly IIdentityServerAuthProviderSettings appSettings; 16 | 17 | public TokenCredentialsClient(IIdentityServerAuthProviderSettings settings) 18 | { 19 | this.appSettings = settings; 20 | } 21 | 22 | public async Task RequestToken() 23 | { 24 | var client = new TokenClient(appSettings.RequestTokenUrl, appSettings.ClientId, appSettings.ClientSecret); 25 | var result = await client.RequestClientCredentialsAsync(appSettings.Scopes).ConfigureAwait(false); 26 | 27 | if (result.IsError) 28 | { 29 | Log.Error($"An error occurred while requesting the access token - {result.Error}"); 30 | return new TokenResult(); 31 | } 32 | 33 | return new TokenResult { AccessToken = result.AccessToken }; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Clients/UserInfoClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Clients 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | using System.Security.Claims; 11 | using Interfaces; 12 | using Logging; 13 | 14 | internal class UserInfoClient : IUserInfoClient 15 | { 16 | private static readonly ILog Log = LogManager.GetLogger(typeof(UserInfoClient)); 17 | 18 | private readonly IIdentityServerAuthProviderSettings appSettings; 19 | 20 | public UserInfoClient(IIdentityServerAuthProviderSettings appSettings) 21 | { 22 | this.appSettings = appSettings; 23 | } 24 | 25 | public async Task> GetClaims(string accessToken) 26 | { 27 | var client = new IdentityModel.Client.UserInfoClient(appSettings.UserInfoUrl); 28 | var response = await client.GetAsync(accessToken).ConfigureAwait(false); 29 | if (response.IsError) 30 | { 31 | Log.Error($"Error calling endpoint {appSettings.UserInfoUrl} - {response.Error}"); 32 | } 33 | 34 | return response.Claims.Select(x => new Claim(x.Type, x.Value)); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/ConfigKeys.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | internal class ConfigKeys 7 | { 8 | public const string OauthProvider = "oauth.provider"; 9 | 10 | public const string AuthRealm = "oauth.IdentityServer.AuthRealm"; 11 | 12 | public const string ClientId = "oauth.IdentityServer.ClientId"; 13 | 14 | public const string ClientSecret = "oauth.IdentityServer.ClientSecret"; 15 | 16 | public const string ClientScopes = "oauth.IdentityServer.Scopes"; 17 | 18 | public const string RoleClaims = "oauth.IdentityServer.RoleClaimNames"; 19 | 20 | public const string PermissionClaimNames = "oauth.IdentityServer.PermissionClaimNames"; 21 | 22 | public const string AuthorizeUrl = "oauth.IdentityServer.AuthorizeUrl"; 23 | 24 | public const string IntrospectUrl = "oauth.IdentityServer.IntrospectUrl"; 25 | 26 | public const string UserInfoUrl = "oauth.IdentityServer.UserInfoUrl"; 27 | 28 | public const string TokenUrl = "oauth.IdentityServer.TokenUrl"; 29 | 30 | public const string CallbackUrl = "oauth.IdentityServer.CallbackUrl"; 31 | 32 | public const string JwksUrl = "oauth.IdentityServer.JwksUrl"; 33 | 34 | public const string Username = "oauth.IdentityServer.Username"; 35 | 36 | public const string Password = "oauth.IdentityServer.Password"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/DefaultClientSecretStore.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | using System.Threading.Tasks; 7 | using Configuration; 8 | using Interfaces; 9 | 10 | class DefaultClientSecretStore : IClientSecretStore 11 | { 12 | private readonly IAppSettings appSettings; 13 | 14 | public DefaultClientSecretStore(IAppSettings appSettings) 15 | { 16 | this.appSettings = appSettings; 17 | } 18 | 19 | public Task GetSecretAsync(string clientId) 20 | { 21 | return Task.FromResult(appSettings.GetString(ConfigKeys.ClientSecret)); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/DocumentDiscoveryResult.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | public class DocumentDiscoveryResult 7 | { 8 | public string AuthorizeUrl { get; set; } 9 | 10 | public string IntrospectUrl { get; set; } 11 | 12 | public string UserInfoUrl { get; set; } 13 | 14 | public string TokenUrl { get; set; } 15 | 16 | public string JwksUrl { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Enums/IdentityServerAuthProviderType.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Enums 5 | { 6 | public enum IdentityServerAuthProviderType 7 | { 8 | /// 9 | /// User Auth Provider - if the user is not authenticated, redirects to Identity Server for them to login 10 | /// 11 | UserAuthProvider = 0, 12 | 13 | /// 14 | /// Service Provider - requires that the service using a Client ID & Secret to authenticate 15 | /// 16 | ServiceProvider = 1, 17 | 18 | /// 19 | /// Impersonation Provider - requires that the requesting service provides an access token which is used to 20 | /// authenticate the user / service 21 | /// 22 | ImpersonationProvider = 2, 23 | 24 | /// 25 | /// Resource Password Flow Provider - requires that the service using a Client ID, Secret, 26 | /// Username and Password to authenticate. 27 | /// 28 | /// 29 | /// 30 | ResourcePasswordFlowProvider = 3, 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Enums/IdentityServerOpenIdAuthorizationFlowType.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Enums 5 | { 6 | public enum IdentityServerOpenIdAuthorizationFlowType 7 | { 8 | /// 9 | /// Authentication using the Hybrid Flow 10 | /// 11 | /// 12 | Hybrid = 0, 13 | 14 | /// 15 | /// Authentication using the Authorization Code Flow 16 | /// 17 | /// 18 | CodeFlow = 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Enums/TokenValidationResult.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Enums 5 | { 6 | public enum TokenValidationResult 7 | { 8 | Error = 0, 9 | 10 | Expired = 1, 11 | 12 | Success = 2 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Exceptions/ConfigurationException.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Exceptions 5 | { 6 | using System; 7 | 8 | public class ConfigurationException : Exception 9 | { 10 | public ConfigurationException(string message) : base(message) 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Extensions/IdentityServerAuthProviderAppSettingsExtensions.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Extensions 5 | { 6 | using System; 7 | using Configuration; 8 | using Enums; 9 | 10 | public static class IdentityServerAuthProviderAppSettingsExtensions 11 | { 12 | private static IAppSettings SetProviderType(this IAppSettings appSettings, IdentityServerAuthProviderType providerType) 13 | { 14 | appSettings.Set(ConfigKeys.OauthProvider, providerType); 15 | return appSettings; 16 | } 17 | 18 | [Obsolete("Use public property on IdentityServerAuthFeature.AuthProviderTyp=IdentityServerAuthProviderType.UserAuthProvider")] 19 | public static IAppSettings SetUserAuthProvider(this IAppSettings appSettings) => appSettings.SetProviderType(IdentityServerAuthProviderType.UserAuthProvider); 20 | 21 | [Obsolete("Use public property on IdentityServerAuthFeature.AuthProviderType=IdentityServerAuthProviderType.ImpersonationProvider")] 22 | public static IAppSettings SetImpersonationAuthProvider(this IAppSettings appSettings) => appSettings.SetProviderType(IdentityServerAuthProviderType.ImpersonationProvider); 23 | 24 | [Obsolete("Use public property on IdentityServerAuthFeature.AuthProviderType = IdentityServerAuthProviderType.ServiceProvide")] 25 | public static IAppSettings SetServiceAuthProvider(this IAppSettings appSettings) => appSettings.SetProviderType(IdentityServerAuthProviderType.ServiceProvider); 26 | 27 | [Obsolete("Use public property IdentityServerAuthFeature.AuthRealm")] 28 | public static IAppSettings SetAuthRealm(this IAppSettings appSettings, string realm) 29 | { 30 | appSettings.Set(ConfigKeys.AuthRealm, realm); 31 | return appSettings; 32 | } 33 | 34 | [Obsolete("Use public property IdentityServerAuthFeature.AuthRealm")] 35 | public static string GetAuthRealm(this IAppSettings appSettings) => appSettings.GetString(ConfigKeys.AuthRealm); 36 | 37 | [Obsolete("Use public property IdentityServerAuthFeature.ClientId")] 38 | public static IAppSettings SetClientId(this IAppSettings appSettings, string clientId) 39 | { 40 | appSettings.Set(ConfigKeys.ClientId, clientId); 41 | return appSettings; 42 | } 43 | 44 | [Obsolete("Use public property IdentityServerAuthFeature.ClientId")] 45 | public static string GetClientId(this IAppSettings appSettings) => appSettings.GetString(ConfigKeys.ClientId); 46 | 47 | [Obsolete("Use public property IdentityServerAuthFeature.ClientSecret")] 48 | public static IAppSettings SetClientSecret(this IAppSettings appSettings, string clientSecret) 49 | { 50 | appSettings.Set(ConfigKeys.ClientSecret, clientSecret); 51 | return appSettings; 52 | } 53 | 54 | [Obsolete("Use public property IdentityServerAuthFeature.Scopes")] 55 | public static IAppSettings SetScopes(this IAppSettings appSettings, string scopes) 56 | { 57 | appSettings.Set(ConfigKeys.ClientScopes, scopes); 58 | return appSettings; 59 | } 60 | 61 | [Obsolete("Use public property IdentityServerAuthFeature.RoleClaimNames")] 62 | public static IAppSettings SetRoleClaims(this IAppSettings appSettings, string roles) 63 | { 64 | appSettings.Set(ConfigKeys.RoleClaims, roles); 65 | return appSettings; 66 | } 67 | 68 | [Obsolete("Use public property IdentityServerAuthFeature.PermissionClaimNames")] 69 | public static IAppSettings SetPermissionClaims(this IAppSettings appSettings, string permissions) 70 | { 71 | appSettings.Set(ConfigKeys.PermissionClaimNames, permissions); 72 | return appSettings; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Extensions/RequestExtensions.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Extensions 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using Web; 9 | 10 | public static class RequestExtensions 11 | { 12 | public static string TidyUrl(this string url) 13 | { 14 | url = url.Trim(); 15 | return !url.EndsWith("/") ? $"{url}/" : url; 16 | } 17 | 18 | public static IEnumerable> GetFragments(this IRequest request) 19 | { 20 | return GetFragments(request.AbsoluteUri); 21 | } 22 | 23 | public static IEnumerable> GetFragments(this string url) 24 | { 25 | var uri = new Uri(url); 26 | var fragment = uri.Fragment; 27 | 28 | if (string.IsNullOrWhiteSpace(fragment)) 29 | { 30 | yield break; 31 | } 32 | 33 | if (fragment.StartsWith("#")) 34 | { 35 | fragment = fragment.Substring(1); 36 | } 37 | 38 | var fragments = fragment.Split('&'); 39 | foreach (var frag in fragments) 40 | { 41 | var pair = frag.Split('='); 42 | yield return Tuple.Create(pair[0], pair[1]); 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/IdentityServerAuthTokens.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | using System.Collections.Generic; 7 | using System.Security.Claims; 8 | using Auth; 9 | 10 | public class IdentityServerAuthTokens : AuthTokens 11 | { 12 | public IdentityServerAuthTokens() 13 | { 14 | Claims = new List(); 15 | } 16 | 17 | public string IdToken { get; set; } 18 | 19 | public string Code { get; set; } 20 | 21 | public string Issuer { get; set; } 22 | 23 | public string Subject { get; set; } 24 | 25 | public string Audience { get; set; } 26 | 27 | public string Expiration { get; set; } 28 | 29 | public string IssuedAt { get; set; } 30 | 31 | public string AuthenticationTime { get; set; } 32 | 33 | public string Nonce { get; set; } 34 | 35 | public IList Claims { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/IdentityServerIdTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | using System; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | using Auth; 11 | using Clients; 12 | using Interfaces; 13 | using Logging; 14 | 15 | using System.IdentityModel.Tokens.Jwt; 16 | using IdentityModel; 17 | using Microsoft.IdentityModel.Tokens; 18 | 19 | class IdentityServerIdTokenValidator : IIdentityServerIdTokenValidator 20 | { 21 | private static readonly ILog Log = LogManager.GetLogger(typeof(IdentityServerIdTokenValidator)); 22 | 23 | private readonly IIdentityServerAuthProviderSettings appSettings; 24 | private readonly TokenValidationParameters tokenValidationParameters; 25 | 26 | public IdentityServerIdTokenValidator(IIdentityServerAuthProviderSettings settings) 27 | { 28 | this.appSettings = settings; 29 | tokenValidationParameters = new TokenValidationParameters(); 30 | } 31 | 32 | internal ISecurityTokenValidator SecurityTokenValidator { get; set; } 33 | 34 | internal IJsonWebKeyClient JsonWebKeyClient { get; set; } 35 | 36 | public async Task Init() 37 | { 38 | if (SecurityTokenValidator == null) 39 | { 40 | SecurityTokenValidator = new JwtSecurityTokenHandler(); 41 | } 42 | 43 | if (JsonWebKeyClient == null) 44 | { 45 | JsonWebKeyClient = new JsonWebKeyClient(appSettings); 46 | } 47 | 48 | var keys = await JsonWebKeyClient.GetAsync().ConfigureAwait(false); 49 | 50 | if (keys == null || keys.Count == 0) 51 | { 52 | Log.Warn($"Unable to load Json Web Kit Set from {appSettings.JwksUrl}"); 53 | } 54 | else 55 | { 56 | tokenValidationParameters.IssuerSigningKeys = keys; 57 | } 58 | 59 | tokenValidationParameters.ValidAudience = appSettings.ClientId; 60 | 61 | var realms = new string[2]; 62 | var realm = appSettings.AuthRealm; 63 | realms[0] = realm.EndsWith("/") ? realm.TrimEnd('/') : $"{realm}/"; 64 | realms[1] = realm; 65 | 66 | tokenValidationParameters.ValidIssuers = realms; 67 | } 68 | 69 | public bool IsValidIdToken(IAuthTokens authTokens, string idToken) 70 | { 71 | var jwtToken = new JwtSecurityToken(idToken); 72 | 73 | var idAuthTokens = authTokens as IdentityServerAuthTokens; 74 | if (idAuthTokens != null) 75 | { 76 | var nonce = jwtToken.Claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Nonce); 77 | if (nonce != null && nonce.Value != idAuthTokens.Nonce) 78 | { 79 | Log.Error("Nonce in id_token does not match the nonce created for the login request - potential replay attack"); 80 | return false; 81 | } 82 | } 83 | 84 | SecurityToken validatedToken = null; 85 | 86 | try 87 | { 88 | SecurityTokenValidator.ValidateToken(idToken, tokenValidationParameters, out validatedToken); 89 | } 90 | catch (Exception exception) 91 | { 92 | Log.Error("Error validating JWT token", exception); 93 | return false; 94 | } 95 | 96 | if (validatedToken == null) 97 | { 98 | Log.Error("Unable to validate id_token"); 99 | return false; 100 | } 101 | 102 | var jwt = validatedToken as JwtSecurityToken; 103 | if (jwt == null) 104 | { 105 | Log.Error("id_token is not a valid jwt token"); 106 | return false; 107 | } 108 | 109 | return true; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IActAsUserGrantTokenClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | 8 | public interface IActAsUserGrantTokenClient 9 | { 10 | Task RequestCode(string accessToken, string accessTokenUrl); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IAuthCodeClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | 8 | public interface IAuthCodeClient 9 | { 10 | Task RequestCode(string code, string callbackUrl); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IClientSecretStore.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | 8 | public interface IClientSecretStore 9 | { 10 | Task GetSecretAsync(string clientId); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IDocumentDiscoveryClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | 8 | public interface IDocumentDiscoveryClient 9 | { 10 | Task GetAsync(string endPoint); 11 | } 12 | } -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IIdentityServerAuthProviderSettings.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | using ServiceStack.Authentication.IdentityServer.Enums; 6 | 7 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 8 | { 9 | using System.Collections.Generic; 10 | 11 | public interface IIdentityServerAuthProviderSettings 12 | { 13 | IdentityServerOpenIdAuthorizationFlowType AuthorizationFlow { get; set; } 14 | 15 | DocumentDiscoveryResult DiscoveryResult { get; set; } 16 | 17 | string AuthRealm { get; } 18 | 19 | string AuthorizeUrl { get; } 20 | 21 | string IntrospectUrl { get; } 22 | 23 | string UserInfoUrl { get; } 24 | 25 | string RequestTokenUrl { get; } 26 | 27 | string CallbackUrl { get; } 28 | 29 | 30 | string ClientId { get; } 31 | 32 | string ClientSecret { get; } 33 | 34 | string JwksUrl { get; } 35 | 36 | string Scopes { get; } 37 | 38 | string Username { get; } 39 | 40 | string Password { get; } 41 | 42 | IList RoleClaimNames { get; } 43 | 44 | IList PermissionClaimNames { get; } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IIdentityServerIdTokenValidator.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | using Auth; 8 | 9 | public interface IIdentityServerIdTokenValidator 10 | { 11 | Task Init(); 12 | 13 | bool IsValidIdToken(IAuthTokens authTokens, string idToken); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IIdentityServerProvider.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | using Auth; 8 | 9 | public interface IIdentityServerProvider : IAuthProvider 10 | { 11 | Task Init(); 12 | 13 | IDocumentDiscoveryClient DocumentDiscoveryClient { get; } 14 | 15 | IIntrospectClient IntrospectionClient { get; } 16 | 17 | IRefreshTokenClient RefreshTokenClient { get; } 18 | 19 | IUserInfoClient UserInfoClient { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IIntrospectClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | using Enums; 8 | 9 | public interface IIntrospectClient 10 | { 11 | Task IsValidToken(string accessToken); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IJsonWebKeyClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | 9 | public interface IJsonWebKeyClient 10 | { 11 | Task> GetAsync(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IRefreshTokenClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | 8 | public interface IRefreshTokenClient 9 | { 10 | Task RefreshToken(string refreshToken); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/ITokenCredentialsClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Threading.Tasks; 7 | 8 | public interface ITokenCredentialsClient 9 | { 10 | Task RequestToken(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Interfaces/IUserInfoClient.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Interfaces 5 | { 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | using System.Security.Claims; 9 | 10 | public interface IUserInfoClient 11 | { 12 | Task> GetClaims(string accessToken); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Providers/ImpersonationAuthProvider.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Providers 5 | { 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | using Auth; 10 | using Clients; 11 | using Interfaces; 12 | using Web; 13 | 14 | public class ImpersonationAuthProvider : IdentityServerAuthProvider 15 | { 16 | public ImpersonationAuthProvider(IIdentityServerAuthProviderSettings appSettings) 17 | : base(appSettings) 18 | { 19 | } 20 | 21 | public override async Task Init() 22 | { 23 | await base.Init().ConfigureAwait(false); 24 | 25 | if (ActAsUserGrantTokenClient == null) ActAsUserGrantTokenClient = new ActAsUserGrantTokenClient(AuthProviderSettings); 26 | } 27 | 28 | public IActAsUserGrantTokenClient ActAsUserGrantTokenClient { get; set; } 29 | 30 | public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) 31 | { 32 | var tokens = Init(authService, ref session, request); 33 | var httpRequest = authService.Request; 34 | 35 | var accessToken = ActAsUserGrantTokenClient.RequestCode( 36 | GetAccessToken(httpRequest, request), 37 | GetReferrer(httpRequest, request)).Result; 38 | 39 | tokens.AccessToken = accessToken; 40 | 41 | // We have the required tokens in the request so now check that they are valid. 42 | session.IsAuthenticated = this.IsValidAccessToken(tokens).Result; 43 | 44 | return OnAuthenticated(authService, session, tokens, new Dictionary()); 45 | } 46 | 47 | private string GetAccessToken(IRequest httpRequest, Authenticate request) 48 | { 49 | const string authorizationToken = "Authorization"; 50 | const string bearerToken = "Bearer "; 51 | 52 | if (!string.IsNullOrWhiteSpace(request?.oauth_token)) 53 | { 54 | return request.oauth_token; 55 | } 56 | 57 | var authorization = httpRequest.Headers[authorizationToken]; 58 | if (!string.IsNullOrWhiteSpace(authorization)) 59 | { 60 | if (authorization.IndexOf(bearerToken, StringComparison.OrdinalIgnoreCase) >= 0) 61 | { 62 | return authorization.Substring(bearerToken.Length).Trim(); 63 | } 64 | } 65 | 66 | throw HttpError.Unauthorized(ErrorMessages.NotAuthenticated); 67 | } 68 | 69 | private string GetReferrer(IRequest httpRequest, Authenticate request) 70 | { 71 | if (!string.IsNullOrWhiteSpace(request?.oauth_verifier)) 72 | { 73 | return request.oauth_verifier; 74 | } 75 | 76 | if (httpRequest.UrlReferrer != null) 77 | { 78 | return httpRequest.UrlReferrer.AbsoluteUri; 79 | } 80 | 81 | throw HttpError.Unauthorized(ErrorMessages.NotAuthenticated); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Providers/ResourcePasswordFlowAuthProvider.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | 5 | using ServiceStack.Configuration; 6 | 7 | namespace ServiceStack.Authentication.IdentityServer.Providers 8 | { 9 | using System.Collections.Generic; 10 | using System.Threading.Tasks; 11 | using Auth; 12 | using Clients; 13 | using Interfaces; 14 | 15 | public class ResourcePasswordFlowAuthProvider : IdentityServerAuthProvider 16 | { 17 | public ResourcePasswordFlowAuthProvider(IIdentityServerAuthProviderSettings appSettings) 18 | : base(appSettings) 19 | { 20 | } 21 | 22 | public override async Task Init() 23 | { 24 | await base.Init().ConfigureAwait(false); 25 | if (TokenCredentialsClient == null) 26 | TokenCredentialsClient = new ResourcePasswordTokenClient(AuthProviderSettings); 27 | } 28 | 29 | public ITokenCredentialsClient TokenCredentialsClient { get; set; } 30 | 31 | public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) 32 | { 33 | RefreshSettings(); 34 | var tokens = Init(authService, ref session, request); 35 | 36 | var reponseToken = TokenCredentialsClient.RequestToken().Result; 37 | 38 | if (!string.IsNullOrWhiteSpace(reponseToken.AccessToken)) 39 | { 40 | tokens.AccessToken = reponseToken.AccessToken; 41 | session.IsAuthenticated = true; 42 | } 43 | 44 | return OnAuthenticated(authService, session, tokens, new Dictionary()); 45 | } 46 | 47 | /// 48 | /// Gets the Referral URL from the Request 49 | /// 50 | /// Auth Service 51 | /// Auth Session 52 | /// Authenticate Request 53 | /// 54 | protected override string GetReferrerUrl(IServiceBase authService, IAuthSession session, Authenticate request = null) 55 | { 56 | string referralUrl = base.GetReferrerUrl(authService, session, request); 57 | 58 | // Special case as the redirect url cannot be sent to identity server as it uses the redirect 59 | // url to authenticate where the request came from. 60 | if (!string.IsNullOrEmpty(authService.Request.QueryString["redirect"])) 61 | { 62 | referralUrl = authService.Request.QueryString["redirect"]; 63 | } 64 | 65 | return referralUrl; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/Providers/ServiceAuthProvider.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Providers 5 | { 6 | using System.Collections.Generic; 7 | using System.Threading.Tasks; 8 | using Auth; 9 | using Clients; 10 | using Interfaces; 11 | 12 | public class ServiceAuthProvider : IdentityServerAuthProvider 13 | { 14 | public ServiceAuthProvider(IIdentityServerAuthProviderSettings appSettings) 15 | : base(appSettings) 16 | { 17 | } 18 | 19 | public override async Task Init() 20 | { 21 | await base.Init().ConfigureAwait(false); 22 | if (TokenCredentialsClient == null) 23 | TokenCredentialsClient = new TokenCredentialsClient(AuthProviderSettings); 24 | } 25 | 26 | public ITokenCredentialsClient TokenCredentialsClient { get; set; } 27 | 28 | public override object Authenticate(IServiceBase authService, IAuthSession session, Authenticate request) 29 | { 30 | RefreshSettings(); 31 | var tokens = Init(authService, ref session, request); 32 | 33 | var reponseToken = TokenCredentialsClient.RequestToken().Result; 34 | 35 | if (!string.IsNullOrWhiteSpace(reponseToken.AccessToken)) 36 | { 37 | tokens.AccessToken = reponseToken.AccessToken; 38 | 39 | session.IsAuthenticated = this.IsValidAccessToken(tokens).Result; 40 | } 41 | 42 | return OnAuthenticated(authService, session, tokens, new Dictionary()); 43 | } 44 | 45 | /// Users the Access token to request the User Info and populates the Tokens 46 | /// User Session 47 | /// Tokens 48 | /// Authentication Info 49 | protected override void LoadUserAuthInfo(AuthUserSession userSession, IAuthTokens tokens, Dictionary authInfo) 50 | { 51 | } 52 | 53 | public override void LoadUserOAuthProvider(IAuthSession authSession, IAuthTokens tokens) 54 | { 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/ServiceRegistration.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | using System.Collections.Generic; 7 | 8 | public class ServiceRegistration 9 | { 10 | public string ClientId { get; set; } 11 | 12 | public string Secret { get; set; } 13 | 14 | public List Roles { get; set; } 15 | 16 | public List Permissions { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/ServiceStack.Authentication.IdentityServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | A ServiceStack plugin for IdentityServer. 5 | Stuart Banks;Scott Mackay 6 | netstandard2.0;net462 7 | true 8 | true 9 | https://www.mozilla.org/en-US/MPL/2.0/ 10 | ServiceStack.Authentication.IdentityServer 11 | ServiceStack;IdentityServer;Authentication 12 | https://github.com/wwwlicious/servicestack-authentication-identityserver/releases 13 | https://servicestack.net/img/logo-32.png 14 | https://github.com/wwwlicious/servicestack-authentication-identityserver 15 | 16 | 17 | 18 | $(DefineConstants);NET462 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/TokenRefreshResult.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | using System; 7 | 8 | public class TokenRefreshResult : TokenResult 9 | { 10 | public string RefreshToken { get; set; } 11 | 12 | public DateTime ExpiresAt { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/ServiceStack.Authentication.IdentityServer/TokenResult.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer 5 | { 6 | public class TokenResult 7 | { 8 | public string AccessToken { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/samples/IdentityServer3.SelfHost/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/samples/IdentityServer3.SelfHost/IdentityServer3.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/samples/IdentityServer3.SelfHost/idsrv3test.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer3.SelfHost/idsrv3test.pfx -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Controllers/AccountController.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Controllers 5 | { 6 | using System.Security.Claims; 7 | using System.Threading.Tasks; 8 | using Extensions; 9 | using Microsoft.AspNetCore.Authentication.Cookies; 10 | using Microsoft.AspNetCore.Http.Authentication; 11 | using Microsoft.AspNetCore.Mvc; 12 | using Models; 13 | using Services; 14 | using Test; 15 | 16 | /// 17 | /// This sample controller implements a typical login/logout/provision workflow for local and external accounts. 18 | /// The login service encapsulates the interactions with the user data store. This data store is in-memory only and cannot be used for production! 19 | /// The interaction service provides a way for the UI to communicate with identityserver for validation and context retrieval 20 | /// 21 | [SecurityHeaders] 22 | public class AccountController : Controller 23 | { 24 | private readonly TestUserStore _users; 25 | private readonly IIdentityServerInteractionService _interaction; 26 | 27 | public AccountController(TestUserStore users, IIdentityServerInteractionService interaction) 28 | { 29 | this._users = users; 30 | this._interaction = interaction; 31 | } 32 | 33 | /// 34 | /// Show login page 35 | /// 36 | [HttpGet] 37 | public async Task Login(string returnUrl) 38 | { 39 | var context = await _interaction.GetAuthorizationContextAsync(returnUrl); 40 | var vm = new LoginViewModel 41 | { 42 | ReturnUrl = returnUrl, 43 | Username = context?.LoginHint 44 | }; 45 | return View(vm); 46 | } 47 | 48 | [HttpPost] 49 | [ValidateAntiForgeryToken] 50 | public async Task Login(LoginInputModel model) 51 | { 52 | if (ModelState.IsValid) 53 | { 54 | if (_users.ValidateCredentials(model.Username, model.Password)) 55 | { 56 | var user = _users.FindByUsername(model.Username); 57 | 58 | await HttpContext.Authentication.SignInAsync(user.SubjectId, user.Username); 59 | 60 | if (_interaction.IsValidReturnUrl(model.ReturnUrl)) 61 | { 62 | return Redirect(model.ReturnUrl); 63 | } 64 | } 65 | } 66 | return Redirect("~/"); 67 | } 68 | 69 | /// 70 | /// Show logout page 71 | /// 72 | [HttpGet] 73 | public async Task Logout(string logoutId) 74 | { 75 | var vm = new LogoutViewModel 76 | { 77 | LogoutId = logoutId 78 | }; 79 | var user = await HttpContext.GetIdentityServerUserAsync(); 80 | if (user == null || !user.Identity.IsAuthenticated) 81 | { 82 | return Redirect("~/"); 83 | } 84 | return View(vm); 85 | } 86 | 87 | /// 88 | /// Handle logout page postback 89 | /// 90 | [HttpPost] 91 | [ValidateAntiForgeryToken] 92 | public async Task Logout(LogoutViewModel model) 93 | { 94 | // delete authentication cookie 95 | await HttpContext.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); 96 | 97 | // set this so UI rendering sees an anonymous user 98 | HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); 99 | 100 | // get context information (client name, post logout redirect URI and iframe for federated signout) 101 | var logout = await _interaction.GetLogoutContextAsync(model.LogoutId); 102 | 103 | var vm = new LoggedOutViewModel 104 | { 105 | PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, 106 | ClientName = logout?.ClientId, 107 | }; 108 | return View("LoggedOut", vm); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Controllers 5 | { 6 | using System.Threading.Tasks; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Models; 9 | using Services; 10 | 11 | [SecurityHeaders] 12 | public class HomeController : Controller 13 | { 14 | private readonly IIdentityServerInteractionService _interaction; 15 | 16 | public HomeController(IIdentityServerInteractionService interaction) 17 | { 18 | _interaction = interaction; 19 | } 20 | 21 | public IActionResult Index() 22 | { 23 | return View(); 24 | } 25 | 26 | /// 27 | /// Shows the error page 28 | /// 29 | public async Task Error(string errorId) 30 | { 31 | var vm = new ErrorViewModel(); 32 | 33 | // retrieve error details from identityserver 34 | var message = await _interaction.GetErrorContextAsync(errorId); 35 | if (message != null) 36 | { 37 | vm.Error = message; 38 | } 39 | 40 | return View("Error", vm); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/IdentityServer4.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.0 5 | true 6 | IdentityServer4.SelfHost 7 | Exe 8 | IdentityServer4.SelfHost 9 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 10 | 11 | 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Models 5 | { 6 | using IdentityServer4.Models; 7 | 8 | public class ErrorViewModel 9 | { 10 | public ErrorMessage Error { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Models/LoggedOutViewModel.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Models 5 | { 6 | public class LoggedOutViewModel 7 | { 8 | public string PostLogoutRedirectUri { get; set; } 9 | public string ClientName { get; set; } 10 | 11 | public bool AutomaticRedirectAfterSignOut { get; set; } 12 | 13 | public string LogoutId { get; set; } 14 | public bool TriggerExternalSignout => ExternalAuthenticationScheme != null; 15 | public string ExternalAuthenticationScheme { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Models/LoginInputModel.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Models 5 | { 6 | using System.ComponentModel.DataAnnotations; 7 | 8 | public class LoginInputModel 9 | { 10 | [Required] 11 | public string Username { get; set; } 12 | [Required] 13 | public string Password { get; set; } 14 | public string ReturnUrl { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Models/LoginViewModel.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Models 5 | { 6 | public class LoginViewModel : LoginInputModel 7 | { 8 | public LoginViewModel() 9 | { 10 | } 11 | 12 | public LoginViewModel(LoginInputModel other) 13 | { 14 | Username = other.Username; 15 | Password = other.Password; 16 | ReturnUrl = other.ReturnUrl; 17 | } 18 | 19 | public string ErrorMessage { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Models/LogoutViewModel.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost.Models 5 | { 6 | public class LogoutViewModel 7 | { 8 | public string LogoutId { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:5000/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "IdentityServer4.SelfHost": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:42977/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/SecurityHeadersAttribute.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer4.SelfHost 5 | { 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.AspNetCore.Mvc.Filters; 8 | 9 | public class SecurityHeadersAttribute : ActionFilterAttribute 10 | { 11 | public override void OnResultExecuting(ResultExecutingContext context) 12 | { 13 | var result = context.Result; 14 | if (result is ViewResult) 15 | { 16 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Type-Options")) 17 | { 18 | context.HttpContext.Response.Headers.Add("X-Content-Type-Options", "nosniff"); 19 | } 20 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Frame-Options")) 21 | { 22 | context.HttpContext.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN"); 23 | } 24 | 25 | var csp = "default-src 'self'"; 26 | // once for standards compliant browsers 27 | if (!context.HttpContext.Response.Headers.ContainsKey("Content-Security-Policy")) 28 | { 29 | context.HttpContext.Response.Headers.Add("Content-Security-Policy", csp); 30 | } 31 | // and once again for IE 32 | if (!context.HttpContext.Response.Headers.ContainsKey("X-Content-Security-Policy")) 33 | { 34 | context.HttpContext.Response.Headers.Add("X-Content-Security-Policy", csp); 35 | } 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/Account/LoggedOut.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Threading.Tasks 2 | @using IdentityServer4.SelfHost.Models 3 | @model LoggedOutViewModel 4 | 5 | @{ 6 | // set this so the layout rendering sees an anonymous user 7 | ViewData["signed-out"] = true; 8 | } 9 | 10 | 24 | 25 | @section scripts 26 | { 27 | @if (Model.AutomaticRedirectAfterSignOut) 28 | { 29 | 30 | } 31 | } -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Threading.Tasks 2 | @using IdentityServer4.SelfHost.Models 3 | @model LoginViewModel 4 | 5 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | 
2 | 11 | 12 |
13 |
14 |

15 | IdentityServer publishes a 16 | discovery document 17 | where you can find metadata and links to all the endpoints, key material, etc. 18 |

19 |
20 |
21 |
22 |
23 |

24 | Here are links to the 25 | source code repository, 26 | and ready to use samples. 27 |

28 |
29 |
30 |
-------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Threading.Tasks 2 | @using IdentityServer4.SelfHost.Models 3 | @model ErrorViewModel 4 | 5 | @{ 6 | var error = Model?.Error?.Error; 7 | var request_id = Model?.Error?.RequestId; 8 | } 9 | 10 |
11 | 14 | 15 |
16 |
17 |
18 | Sorry, there was an error 19 | 20 | @if (error != null) 21 | { 22 | 23 | 24 | : @error 25 | 26 | 27 | } 28 |
29 | 30 | @if (request_id != null) 31 | { 32 |
Request Id: @request_id
33 | } 34 |
35 |
36 |
-------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @using IdentityServer4.Extensions 2 | @{ 3 | string name = null; 4 | if (!true.Equals(ViewData["signed-out"])) 5 | { 6 | var user = await Context.GetIdentityServerUserAsync(); 7 | name = user?.FindFirst("name")?.Value; 8 | } 9 | } 10 | 11 | 12 | 13 | 14 | 15 | 16 | IdentityServer4 17 | 18 | 19 | 20 | 21 | 22 | 23 | 53 | 54 |
55 | @RenderBody() 56 |
57 | 58 | 59 | 60 | @RenderSection("scripts", required: false) 61 | 62 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/Shared/_ValidationSummary.cshtml: -------------------------------------------------------------------------------- 1 | @if (ViewContext.ModelState.IsValid == false) 2 | { 3 |
4 | Error 5 |
6 |
7 | } -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using IdentityServer4.SelfHost 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 65px; 3 | } 4 | .navbar-header { 5 | position: relative; 6 | top: -4px; 7 | } 8 | .navbar-brand > .icon-banner { 9 | position: relative; 10 | top: -2px; 11 | display: inline; 12 | } 13 | .icon { 14 | position: relative; 15 | top: -10px; 16 | } 17 | .logged-out iframe { 18 | display: none; 19 | width: 0; 20 | height: 0; 21 | } 22 | .page-consent .client-logo { 23 | float: left; 24 | } 25 | .page-consent .client-logo img { 26 | width: 80px; 27 | height: 80px; 28 | } 29 | .page-consent .consent-buttons { 30 | margin-top: 25px; 31 | } 32 | .page-consent .consent-form .consent-scopecheck { 33 | display: inline-block; 34 | margin-right: 5px; 35 | } 36 | .page-consent .consent-form .consent-description { 37 | margin-left: 25px; 38 | } 39 | .page-consent .consent-form .consent-description label { 40 | font-weight: normal; 41 | } 42 | .page-consent .consent-form .consent-remember { 43 | padding-left: 16px; 44 | } -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/css/site.less: -------------------------------------------------------------------------------- 1 | body { 2 | margin-top: 65px; 3 | } 4 | 5 | .navbar-header { 6 | position:relative; 7 | top:-4px; 8 | } 9 | 10 | .navbar-brand > .icon-banner { 11 | position:relative; 12 | top:-2px; 13 | display:inline; 14 | } 15 | 16 | .icon { 17 | position:relative; 18 | top:-10px; 19 | } 20 | 21 | .logged-out iframe { 22 | display:none; 23 | width:0; 24 | height:0; 25 | } 26 | 27 | .page-consent { 28 | .client-logo { 29 | float: left; 30 | 31 | img { 32 | width: 80px; 33 | height: 80px; 34 | } 35 | } 36 | 37 | .consent-buttons { 38 | margin-top: 25px; 39 | } 40 | 41 | .consent-form { 42 | .consent-scopecheck { 43 | display: inline-block; 44 | margin-right: 5px; 45 | } 46 | 47 | .consent-scopecheck[disabled] { 48 | //visibility:hidden; 49 | } 50 | 51 | .consent-description { 52 | margin-left: 25px; 53 | 54 | label { 55 | font-weight: normal; 56 | } 57 | } 58 | 59 | .consent-remember { 60 | padding-left: 16px; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/css/site.min.css: -------------------------------------------------------------------------------- 1 | body{margin-top:65px;}.navbar-header{position:relative;top:-4px;}.navbar-brand>.icon-banner{position:relative;top:-2px;display:inline;}.icon{position:relative;top:-10px;}.logged-out iframe{display:none;width:0;height:0;}.page-consent .client-logo{float:left;}.page-consent .client-logo img{width:80px;height:80px;}.page-consent .consent-buttons{margin-top:25px;}.page-consent .consent-form .consent-scopecheck{display:inline-block;margin-right:5px;}.page-consent .consent-form .consent-description{margin-left:25px;}.page-consent .consent-form .consent-description label{font-weight:normal;}.page-consent .consent-form .consent-remember{padding-left:16px;} -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/icon.jpg -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/icon.png -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/js/signout-redirect.js: -------------------------------------------------------------------------------- 1 | window.addEventListener("load", function () { 2 | var a = document.querySelector("a.PostLogoutRedirectUri"); 3 | if (a) { 4 | window.location = a.href; 5 | } 6 | }); 7 | -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wwwlicious/servicestack-authentication-identityserver/99714115cd98a501e38e298af20d35b4df3ecb02/src/samples/IdentityServer4.SelfHost/wwwroot/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/AppHost.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.Api.SelfHost 5 | { 6 | using Funq; 7 | using global::ServiceStack; 8 | using global::ServiceStack.Authentication.IdentityServer; 9 | using global::ServiceStack.Authentication.IdentityServer.Enums; 10 | using ServiceInterface; 11 | 12 | public class AppHost : AppSelfHostBase 13 | { 14 | /// 15 | /// Default constructor. 16 | /// Base constructor requires a name and assembly to locate web service classes. 17 | /// 18 | public AppHost() 19 | : base("ImpersonateAuthProvider.ServiceStack.Api.SelfHost", typeof(MyServices).Assembly) 20 | { 21 | 22 | } 23 | 24 | /// 25 | /// Application specific configuration 26 | /// This method should initialize any IoC resources utilized by your web service classes. 27 | /// 28 | /// 29 | public override void Configure(Container container) 30 | { 31 | this.Plugins.Add(new IdentityServerAuthFeature 32 | { 33 | AuthProviderType = IdentityServerAuthProviderType.ImpersonationProvider, 34 | AuthRealm = "http://localhost:5000/", 35 | ClientId = "ImpersonateAuthProvider.ServiceStack.Api.SelfHost", 36 | ClientSecret = "a9c08d7b-ffc2-49f4-99c9-ce232d9f0cf6", 37 | Scopes = "openid ImpersonateAuthProvider.ServiceStack.Api.SelfHost", 38 | RoleClaims = "ImpersonateAuthProvider.ServiceStack.Api.SelfHost.Role", 39 | PermissionClaims = "ImpersonateAuthProvider.ServiceStack.Api.SelfHost.Permission" 40 | }); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/ImpersonateAuthProvider.ServiceStack.Api.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | Exe 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.Api.SelfHost 5 | { 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | using global::ServiceStack.Text; 10 | 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | Thread.Sleep(5000); 16 | 17 | new AppHost().Init().Start("http://*:5003/"); 18 | "ServiceStack SelfHost listening at http://localhost:5003/".Print(); 19 | Process.Start("http://localhost:5003/"); 20 | 21 | Console.ReadLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/ServiceInterface/ExternalServices.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceStack.Api.SelfHost.ServiceInterface 2 | { 3 | using ServiceStack; 4 | using ServiceModel; 5 | 6 | public class MyServices : Service 7 | { 8 | [RequiredRole("Manager")] 9 | [RequiredPermission("CanBuyStuff")] 10 | public object Any(Hello request) 11 | { 12 | var session = this.GetSession(); 13 | 14 | if (session.HasPermission( "CanSeeAllOrders", null)) 15 | { 16 | return new HelloResponse 17 | { 18 | Result = $"Whoooooaaaa! {request.Name}, you must be a big deal as you have the CanSeeAllOrders permission" 19 | }; 20 | } 21 | else 22 | { 23 | return new HelloResponse 24 | { 25 | Result = $"Hello, {request.Name} I'm in a separate Service Stack Instance!" 26 | }; 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/ServiceInterface/MyServices.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.Api.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using ServiceModel; 8 | 9 | public class MyServices : Service 10 | { 11 | [RequiredRole("Manager")] 12 | [RequiredPermission("CanBuyStuff")] 13 | public object Any(Hello request) 14 | { 15 | var session = this.GetSession(); 16 | 17 | if (session.HasPermission("CanSeeAllOrders", null)) 18 | { 19 | return new HelloResponse 20 | { 21 | Result = $"Whoooooaaaa! {request.Name}, you must be a big deal as you have the CanSeeAllOrders permission" 22 | }; 23 | } 24 | else 25 | { 26 | return new HelloResponse 27 | { 28 | Result = $"Hello, {request.Name} I'm in a separate Service Stack Instance!" 29 | }; 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/ServiceModel/External.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceStack.Api.SelfHost.ServiceModel 2 | { 3 | using ServiceStack; 4 | 5 | [Route("/hello/{Name}")] 6 | public class Hello : IReturn 7 | { 8 | public string Name { get; set; } 9 | } 10 | 11 | public class HelloResponse 12 | { 13 | public string Result { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.Api.SelfHost/ServiceModel/Hello.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.Api.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/hello/{Name}")] 9 | public class Hello : IReturn 10 | { 11 | public string Name { get; set; } 12 | } 13 | 14 | public class HelloResponse 15 | { 16 | public string Result { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/AppHost.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.SelfHost 5 | { 6 | using System.IO; 7 | using Funq; 8 | using global::ServiceStack; 9 | using global::ServiceStack.Authentication.IdentityServer; 10 | using global::ServiceStack.Authentication.IdentityServer.Enums; 11 | using global::ServiceStack.Logging; 12 | using global::ServiceStack.Razor; 13 | using ServiceInterface; 14 | 15 | public class AppHost : AppSelfHostBase 16 | { 17 | 18 | private readonly string serviceUrl; 19 | 20 | /// 21 | /// Default constructor. 22 | /// Base constructor requires a name and assembly to locate web service classes. 23 | /// 24 | public AppHost(string serviceUrl) 25 | : base("ImpersonateAuthProvider.ServiceStack.SelfHost", typeof (MyServices).Assembly) 26 | { 27 | this.serviceUrl = serviceUrl; 28 | 29 | LogManager.LogFactory = new ConsoleLogFactory(true); 30 | } 31 | 32 | /// 33 | /// Application specific configuration 34 | /// This method should initialize any IoC resources utilized by your web service classes. 35 | /// 36 | /// 37 | public override void Configure(Container container) 38 | { 39 | //Config examples 40 | //this.Plugins.Add(new PostmanFeature()); 41 | //this.Plugins.Add(new CorsFeature()); 42 | 43 | this.Plugins.Add(new RazorFormat()); 44 | SetConfig(new HostConfig 45 | { 46 | #if DEBUG 47 | DebugMode = true, 48 | WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..")), 49 | #endif 50 | WebHostUrl = serviceUrl 51 | }); 52 | 53 | this.Plugins.Add(new IdentityServerAuthFeature(AppSettings, new JsonServiceClient("http://localhost:5003/")) 54 | { 55 | AuthProviderType = IdentityServerAuthProviderType.UserAuthProvider, 56 | AuthRealm = "http://localhost:5000/", 57 | ClientId = "ImpersonateAuthProvider.ServiceStack.SelfHost", 58 | ClientSecret = "99e1ae38-866c-4ff4-b9e0-dcfaeb3dbb4a", 59 | Scopes = "openid profile ImpersonateAuthProvider.ServiceStack.SelfHost email offline_access" 60 | }); 61 | } 62 | } 63 | } -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/ImpersonateAuthProvider.ServiceStack.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.SelfHost 5 | { 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | using global::ServiceStack.Text; 10 | 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | Thread.Sleep(5000); 16 | 17 | new AppHost("http://localhost:5001/").Init().Start("http://*:5001/"); 18 | "ServiceStack Self Host with Razor listening at http://localhost:5001 ".Print(); 19 | Process.Start("http://localhost:5001/"); 20 | 21 | Console.ReadLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/ServiceInterface/MyServices.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using global::ServiceStack.Authentication.IdentityServer.Providers; 8 | using ServiceModel; 9 | 10 | public class MyServices : Service 11 | { 12 | [Authenticate(IdentityServerAuthProvider.Name)] 13 | public object Get(Hello request) 14 | { 15 | var session = GetSession(); 16 | 17 | return new HelloResponse { Result = $"Hello, {session.FirstName}!" }; 18 | } 19 | 20 | public object Post(Hello request) 21 | { 22 | return new HelloResponse { Result = $"Hello, {request.Name}!" }; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/ServiceInterface/SecureService.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using global::ServiceStack.Authentication.IdentityServer.Providers; 8 | using ServiceModel; 9 | 10 | [Authenticate(IdentityServerAuthProvider.Name)] 11 | public class SecureService : Service 12 | { 13 | public IServiceClient ExternalServiceClient { get; set; } 14 | 15 | public object Any(Secure request) 16 | { 17 | var response = ExternalServiceClient.Get(new Hello {Name = request.Name}); 18 | return new SecureResponse {Result = response.Result}; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/ServiceModel/Hello.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/hello")] 9 | [Route("/hello/{Name}")] 10 | public class Hello : IReturn 11 | { 12 | public string Name { get; set; } 13 | } 14 | 15 | public class HelloResponse 16 | { 17 | public string Result { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/ServiceModel/Secure.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ImpersonateAuthProvider.ServiceStack.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/secure")] 9 | [Route("/secure/{Name}")] 10 | public class Secure : IReturn 11 | { 12 | public string Name { get; set; } 13 | } 14 | 15 | public class SecureResponse 16 | { 17 | public string Result { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/Views/Hello.cshtml: -------------------------------------------------------------------------------- 1 | @using ImpersonateAuthProvider.ServiceStack.SelfHost.ServiceModel 2 | @using ServiceStack 3 | @inherits ServiceStack.Razor.ViewPage 4 | 5 |

@Model.Result

6 | 7 |

< home

8 | 9 |
10 |
11 | 12 | 13 |
14 |
-------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/Views/Secure.cshtml: -------------------------------------------------------------------------------- 1 | @inherits ServiceStack.Razor.ViewPage 2 |

@Model.Result

3 | 4 |

< home

-------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ServiceStack Self Host with Razor 5 | 45 | 46 | 47 |

ServiceStack Self Host with Razor

48 |
49 | @RenderBody() 50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /src/samples/ImpersonateAuthProvider.ServiceStack.SelfHost/default.cshtml: -------------------------------------------------------------------------------- 1 | @using ImpersonateAuthProvider.ServiceStack.SelfHost.ServiceModel 2 | @using ServiceStack 3 | @inherits ServiceStack.Razor.ViewPage 4 | 5 | @{ 6 | ViewBag.Title = "ServiceStack Self Host with Razor"; 7 | } 8 | 9 |

Hello World Service

10 | 11 |

Access some secure content here!

-------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/AppHost.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.Api.SelfHost 5 | { 6 | using Funq; 7 | using global::ServiceStack; 8 | using global::ServiceStack.Authentication.IdentityServer; 9 | using global::ServiceStack.Authentication.IdentityServer.Enums; 10 | using global::ServiceStack.Logging; 11 | using ServiceInterface; 12 | 13 | public class AppHost : AppSelfHostBase 14 | { 15 | /// 16 | /// Default constructor. 17 | /// Base constructor requires a name and assembly to locate web service classes. 18 | /// 19 | public AppHost() 20 | : base("ImpersonateAuthProvider.ServiceStack.Api.SelfHost", typeof(MyServices).Assembly) 21 | { 22 | LogManager.LogFactory = new ConsoleLogFactory(true); 23 | } 24 | 25 | /// 26 | /// Application specific configuration 27 | /// This method should initialize any IoC resources utilized by your web service classes. 28 | /// 29 | /// 30 | public override void Configure(Container container) 31 | { 32 | this.Plugins.Add(new IdentityServerAuthFeature 33 | { 34 | AuthProviderType = IdentityServerAuthProviderType.ServiceProvider, 35 | AuthRealm = "http://localhost:5000/", 36 | ClientId = "ServiceAuthProvider.ServiceStack.Api.SelfHost", 37 | ClientSecret = "358bbaad-7921-4785-999e-adfbef1eb1d1", 38 | Scopes = "ServiceAuthProvider.ServiceStack.Api.SelfHost" 39 | }); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.Api.SelfHost 5 | { 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | using global::ServiceStack.Text; 10 | 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | Thread.Sleep(5000); 16 | 17 | new AppHost().Init().Start("http://*:5003/"); 18 | "ServiceStack SelfHost listening at http://localhost:5003/".Print(); 19 | Process.Start("http://localhost:5003/"); 20 | 21 | Console.ReadLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/ServiceAuthProvider.ServiceStack.Api.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | Exe 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/ServiceInterface/ExternalServices.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceStack.Api.SelfHost.ServiceInterface 2 | { 3 | using ServiceStack; 4 | using ServiceModel; 5 | 6 | public class MyServices : Service 7 | { 8 | [RequiredRole("Manager")] 9 | [RequiredPermission("CanBuyStuff")] 10 | public object Any(Hello request) 11 | { 12 | var session = this.GetSession(); 13 | 14 | if (session.HasPermission("CanSeeAllOrders", null)) 15 | { 16 | return new HelloResponse 17 | { 18 | Result = $"Whoooooaaaa! {request.Name}, you must be a big deal as you have the CanSeeAllOrders permission" 19 | }; 20 | } 21 | else 22 | { 23 | return new HelloResponse 24 | { 25 | Result = $"Hello, {request.Name} I'm in a separate Service Stack Instance!" 26 | }; 27 | } 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/ServiceInterface/MyServices.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.Api.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using global::ServiceStack.Authentication.IdentityServer.Providers; 8 | using ServiceModel; 9 | 10 | public class MyServices : Service 11 | { 12 | [Authenticate(IdentityServerAuthProvider.Name)] 13 | public object Any(Hello request) 14 | { 15 | return new HelloResponse 16 | { 17 | Result = $"Hello, {request.Name} I'm resource only Service Stack Instance!" 18 | }; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/ServiceModel/External.cs: -------------------------------------------------------------------------------- 1 | namespace ServiceStack.Api.SelfHost.ServiceModel 2 | { 3 | using ServiceStack; 4 | 5 | [Route("/hello/{Name}")] 6 | public class Hello : IReturn 7 | { 8 | public string Name { get; set; } 9 | } 10 | 11 | public class HelloResponse 12 | { 13 | public string Result { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.Api.SelfHost/ServiceModel/Hello.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.Api.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/hello/{Name}")] 9 | public class Hello : IReturn 10 | { 11 | public string Name { get; set; } 12 | } 13 | 14 | public class HelloResponse 15 | { 16 | public string Result { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/AppHost.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.SelfHost 5 | { 6 | using System.IO; 7 | using Funq; 8 | using global::ServiceStack; 9 | using global::ServiceStack.Authentication.IdentityServer; 10 | using global::ServiceStack.Authentication.IdentityServer.Enums; 11 | using global::ServiceStack.Logging; 12 | using global::ServiceStack.Razor; 13 | using ServiceInterface; 14 | 15 | public class AppHost : AppSelfHostBase 16 | { 17 | 18 | private readonly string serviceUrl; 19 | 20 | /// 21 | /// Default constructor. 22 | /// Base constructor requires a name and assembly to locate web service classes. 23 | /// 24 | public AppHost(string serviceUrl) 25 | : base("ServiceAuthProvider.ServiceStack.SelfHost", typeof (MyServices).Assembly) 26 | { 27 | this.serviceUrl = serviceUrl; 28 | 29 | LogManager.LogFactory = new ConsoleLogFactory(true); 30 | } 31 | 32 | /// 33 | /// Application specific configuration 34 | /// This method should initialize any IoC resources utilized by your web service classes. 35 | /// 36 | /// 37 | public override void Configure(Container container) 38 | { 39 | //Config examples 40 | 41 | this.Plugins.Add(new RazorFormat()); 42 | SetConfig(new HostConfig 43 | { 44 | #if DEBUG 45 | DebugMode = true, 46 | WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..")), 47 | #endif 48 | WebHostUrl = serviceUrl 49 | }); 50 | 51 | this.Plugins.Add(new IdentityServerAuthFeature 52 | { 53 | AuthProviderType = IdentityServerAuthProviderType.UserAuthProvider, 54 | AuthRealm = "http://localhost:5000/", 55 | ClientId = "ServiceAuthProvider.ServiceStack.SelfHost", 56 | ClientSecret = "26631ded-6165-4bdd-900d-182028495a8c", 57 | Scopes = "openid profile ServiceAuthProvider.ServiceStack.SelfHost email offline_access" 58 | }); 59 | } 60 | } 61 | } -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.SelfHost 5 | { 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | using global::ServiceStack.Text; 10 | 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | Thread.Sleep(5000); 16 | 17 | new AppHost("http://localhost:5001/").Init().Start("http://*:5001/"); 18 | "ServiceStack Self Host with Razor listening at http://localhost:5001 ".Print(); 19 | Process.Start("http://localhost:5001/"); 20 | 21 | Console.ReadLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/ServiceAuthProvider.ServiceStack.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/ServiceInterface/MyServices.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using global::ServiceStack.Authentication.IdentityServer.Providers; 8 | using ServiceModel; 9 | 10 | public class MyServices : Service 11 | { 12 | [Authenticate(IdentityServerAuthProvider.Name)] 13 | public object Get(Hello request) 14 | { 15 | var session = GetSession(); 16 | 17 | return new HelloResponse { Result = $"Hello, {session.FirstName}!" }; 18 | } 19 | 20 | public object Post(Hello request) 21 | { 22 | return new HelloResponse { Result = $"Hello, {request.Name}!" }; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/ServiceInterface/SecureService.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.SelfHost.ServiceInterface 5 | { 6 | using System; 7 | using global::ServiceStack; 8 | using global::ServiceStack.Authentication.IdentityServer.Providers; 9 | using ServiceModel; 10 | 11 | [Authenticate(IdentityServerAuthProvider.Name)] 12 | public class SecureService : Service 13 | { 14 | public object Any(Secure request) 15 | { 16 | var serviceClient = new JsonServiceClient("http://localhost:5003/"); 17 | serviceClient.Post(new Authenticate { provider = IdentityServerAuthProvider.Name }); 18 | 19 | var response = serviceClient.Get(new Hello { Name = request.Name }); 20 | return new SecureResponse { Result = response.Result }; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/ServiceModel/Hello.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/hello")] 9 | [Route("/hello/{Name}")] 10 | public class Hello : IReturn 11 | { 12 | public string Name { get; set; } 13 | } 14 | 15 | public class HelloResponse 16 | { 17 | public string Result { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/ServiceModel/Secure.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceAuthProvider.ServiceStack.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/secure")] 9 | [Route("/secure/{Name}")] 10 | public class Secure : IReturn 11 | { 12 | public string Name { get; set; } 13 | } 14 | 15 | public class SecureResponse 16 | { 17 | public string Result { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/Views/Hello.cshtml: -------------------------------------------------------------------------------- 1 | @using ServiceAuthProvider.ServiceStack.SelfHost.ServiceModel 2 | @using ServiceStack 3 | @inherits ServiceStack.Razor.ViewPage 4 | 5 |

@Model.Result

6 | 7 |

< home

8 | 9 |
10 |
11 | 12 | 13 |
14 |
-------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/Views/Secure.cshtml: -------------------------------------------------------------------------------- 1 | @inherits ServiceStack.Razor.ViewPage 2 |

@Model.Result

3 | 4 |

< home

-------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ServiceStack Self Host with Razor 5 | 45 | 46 | 47 |

ServiceStack Self Host with Razor

48 |
49 | @RenderBody() 50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /src/samples/ServiceAuthProvider.ServiceStack.SelfHost/default.cshtml: -------------------------------------------------------------------------------- 1 | @using ServiceAuthProvider.ServiceStack.SelfHost.ServiceModel 2 | @using ServiceStack 3 | @inherits ServiceStack.Razor.ViewPage 4 | 5 | @{ 6 | ViewBag.Title = "ServiceStack Self Host with Razor"; 7 | } 8 | 9 |

Hello World Service

10 | 11 |

Access some secure content here!

-------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/AppHost.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.Core.SelfHost 5 | { 6 | using Funq; 7 | using global::ServiceStack; 8 | using global::ServiceStack.Authentication.IdentityServer; 9 | using global::ServiceStack.Authentication.IdentityServer.Enums; 10 | using global::ServiceStack.Mvc; 11 | 12 | public class AppHost : AppHostBase 13 | { 14 | private readonly string serviceUrl; 15 | 16 | public AppHost(string serviceUrl) 17 | : base("UserAuthProvider.ServiceStack.Core.SelfHost", typeof(AppHost).GetAssembly()) 18 | { 19 | this.serviceUrl = serviceUrl; 20 | } 21 | 22 | public override void Configure(Container container) 23 | { 24 | this.Plugins.Add(new RazorFormat()); 25 | 26 | SetConfig(new HostConfig 27 | { 28 | #if DEBUG 29 | DebugMode = true, 30 | #endif 31 | WebHostUrl = serviceUrl 32 | }); 33 | 34 | this.Plugins.Add(new IdentityServerAuthFeature 35 | { 36 | AuthProviderType = IdentityServerAuthProviderType.UserAuthProvider, 37 | AuthRealm = "http://localhost:5000/", 38 | ClientId = "UserAuthProvider.ServiceStack.SelfHost", 39 | ClientSecret = "F621F470-9731-4A25-80EF-67A6F7C5F4B8", 40 | Scopes = "openid profile UserAuthProvider.ServiceStack.SelfHost email offline_access" 41 | }); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using Microsoft.AspNetCore.Hosting; 10 | 11 | namespace UserAuthProvider.ServiceStack.Core.SelfHost 12 | { 13 | public class Program 14 | { 15 | public static void Main(string[] args) 16 | { 17 | var host = new WebHostBuilder() 18 | .UseKestrel() 19 | .UseContentRoot(Directory.GetCurrentDirectory()) 20 | .UseIISIntegration() 21 | .UseStartup() 22 | .Build(); 23 | 24 | host.Run(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:5001", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "UserAuthProvider.ServiceStack.Core.SelfHost": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "launchUrl": "http://localhost:5001", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/ServiceInterface/MyServices.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.Core.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using ServiceModel; 8 | 9 | public class MyServices : Service 10 | { 11 | [Authenticate] 12 | public object Get(Hello request) 13 | { 14 | var session = GetSession(); 15 | 16 | return new HelloResponse { Result = $"Hello, {session.FirstName}!" }; 17 | } 18 | 19 | public object Post(Hello request) 20 | { 21 | return new HelloResponse { Result = $"Hello, {request.Name}!" }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/ServiceModel/Hello.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.Core.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/hello")] 9 | [Route("/hello/{Name}")] 10 | public class Hello : IReturn 11 | { 12 | public string Name { get; set; } 13 | } 14 | 15 | public class HelloResponse 16 | { 17 | public string Result { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/Startup.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Threading.Tasks; 8 | using Microsoft.AspNetCore.Builder; 9 | using Microsoft.AspNetCore.Hosting; 10 | using Microsoft.AspNetCore.Http; 11 | using Microsoft.Extensions.DependencyInjection; 12 | using Microsoft.Extensions.Logging; 13 | 14 | namespace UserAuthProvider.ServiceStack.Core.SelfHost 15 | { 16 | using global::ServiceStack; 17 | using global::ServiceStack.Host.Handlers; 18 | using global::ServiceStack.Mvc; 19 | using Serilog; 20 | 21 | public class Startup 22 | { 23 | public Startup(IHostingEnvironment env) 24 | { 25 | Log.Logger = new LoggerConfiguration() 26 | .MinimumLevel.Verbose() 27 | .Enrich.FromLogContext() 28 | .WriteTo.Seq("http://localhost:5341") 29 | .CreateLogger(); 30 | } 31 | 32 | // This method gets called by the runtime. Use this method to add services to the container. 33 | // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940 34 | public void ConfigureServices(IServiceCollection services) 35 | { 36 | services.AddMvc(); 37 | } 38 | 39 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 40 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 41 | { 42 | loggerFactory.AddConsole(); 43 | 44 | loggerFactory.AddSerilog(); 45 | 46 | if (env.IsDevelopment()) 47 | { 48 | app.UseDeveloperExceptionPage(); 49 | } 50 | 51 | app.UseServiceStack(new AppHost("http://localhost:5001")); 52 | 53 | app.Use(new RequestInfoHandler()); 54 | 55 | app.UseMvc(routes => 56 | { 57 | routes.MapRoute( 58 | name: "default", 59 | template: "{controller=Home}/{action=Index}/{id?}"); 60 | }); 61 | 62 | app.Use(new RazorHandler("/notfound")); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/UserAuthProvider.ServiceStack.Core.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.0 5 | true 6 | UserAuthProvider.ServiceStack.Core.SelfHost 7 | Exe 8 | UserAuthProvider.ServiceStack.Core.SelfHost 9 | $(PackageTargetFallback);dotnet5.6;portable-net45+win8 10 | 11 | 12 | 13 | 14 | PreserveNewest 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/Views/Hello.cshtml: -------------------------------------------------------------------------------- 1 | @model UserAuthProvider.ServiceStack.Core.SelfHost.ServiceModel.HelloResponse 2 | @{ 3 | Layout = "_Layout"; 4 | } 5 | 6 |

@Model.Result

7 | 8 |

< home

9 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ServiceStack Self Host with Razor 5 | 45 | 46 | 47 |

ServiceStack Self Host with Razor

48 |
49 | @RenderBody() 50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.Core.SelfHost/wwwroot/default.cshtml: -------------------------------------------------------------------------------- 1 | @using ServiceStack 2 | @using UserAuthProvider.ServiceStack.Core.SelfHost.ServiceModel 3 | @{ 4 | ViewBag.Title = "ServiceStack Self Host with Razor"; 5 | Layout = "_Layout"; 6 | } 7 | 8 |

Hello World Service

9 | 10 |

Access some secure content here!

-------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/AppHost.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.SelfHost 5 | { 6 | using System.IO; 7 | using Funq; 8 | using global::ServiceStack; 9 | using global::ServiceStack.Authentication.IdentityServer; 10 | using global::ServiceStack.Authentication.IdentityServer.Enums; 11 | using global::ServiceStack.Logging; 12 | using global::ServiceStack.Razor; 13 | using ServiceInterface; 14 | 15 | public class AppHost : AppSelfHostBase 16 | { 17 | 18 | private readonly string serviceUrl; 19 | 20 | /// 21 | /// Default constructor. 22 | /// Base constructor requires a name and assembly to locate web service classes. 23 | /// 24 | public AppHost(string serviceUrl) 25 | : base("UserAuthProvider.ServiceStack.SelfHost", typeof (MyServices).Assembly) 26 | { 27 | this.serviceUrl = serviceUrl; 28 | 29 | LogManager.LogFactory = new ConsoleLogFactory(true); 30 | } 31 | 32 | /// 33 | /// Application specific configuration 34 | /// This method should initialize any IoC resources utilized by your web service classes. 35 | /// 36 | /// 37 | public override void Configure(Container container) 38 | { 39 | this.Plugins.Add(new RazorFormat()); 40 | SetConfig(new HostConfig 41 | { 42 | #if DEBUG 43 | DebugMode = true, 44 | WebHostPhysicalPath = Path.GetFullPath(Path.Combine("~".MapServerPath(), "..", "..")), 45 | #endif 46 | WebHostUrl = serviceUrl 47 | }); 48 | 49 | this.Plugins.Add(new IdentityServerAuthFeature 50 | { 51 | AuthProviderType = IdentityServerAuthProviderType.UserAuthProvider, 52 | AuthRealm = "http://localhost:5000/", 53 | ClientId = "UserAuthProvider.ServiceStack.SelfHost", 54 | ClientSecret = "F621F470-9731-4A25-80EF-67A6F7C5F4B8", 55 | Scopes = "openid profile UserAuthProvider.ServiceStack.SelfHost email offline_access" 56 | }); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/Program.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.SelfHost 5 | { 6 | using System; 7 | using System.Diagnostics; 8 | using System.Threading; 9 | using global::ServiceStack.Text; 10 | 11 | class Program 12 | { 13 | static void Main(string[] args) 14 | { 15 | Thread.Sleep(5000); 16 | 17 | new AppHost("http://localhost:5001/").Init().Start("http://*:5001/"); 18 | "ServiceStack Self Host with Razor listening at http://localhost:5001 ".Print(); 19 | Process.Start("http://localhost:5001/"); 20 | 21 | Console.ReadLine(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/ServiceInterface/MyServices.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.SelfHost.ServiceInterface 5 | { 6 | using global::ServiceStack; 7 | using global::ServiceStack.Authentication.IdentityServer.Providers; 8 | using ServiceModel; 9 | 10 | public class MyServices : Service 11 | { 12 | [Authenticate(IdentityServerAuthProvider.Name)] 13 | public object Get(Hello request) 14 | { 15 | var session = GetSession(); 16 | 17 | return new HelloResponse { Result = $"Hello, {session.FirstName}!" }; 18 | } 19 | 20 | public object Post(Hello request) 21 | { 22 | return new HelloResponse { Result = $"Hello, {request.Name}!" }; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/ServiceModel/Hello.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace UserAuthProvider.ServiceStack.SelfHost.ServiceModel 5 | { 6 | using global::ServiceStack; 7 | 8 | [Route("/hello")] 9 | [Route("/hello/{Name}")] 10 | public class Hello : IReturn 11 | { 12 | public string Name { get; set; } 13 | } 14 | 15 | public class HelloResponse 16 | { 17 | public string Result { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/UserAuthProvider.ServiceStack.SelfHost.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | Exe 5 | 6 | 7 | 8 | 9 | 10 | 11 | PreserveNewest 12 | 13 | 14 | 15 | PreserveNewest 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/Views/Hello.cshtml: -------------------------------------------------------------------------------- 1 | @using ServiceStack 2 | @inherits ServiceStack.Razor.ViewPage 3 | 4 |

@Model.Result

5 | 6 |

< home

7 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ServiceStack Self Host with Razor 5 | 45 | 46 | 47 |

ServiceStack Self Host with Razor

48 |
49 | @RenderBody() 50 |
51 | 52 | 53 | -------------------------------------------------------------------------------- /src/samples/UserAuthProvider.ServiceStack.SelfHost/default.cshtml: -------------------------------------------------------------------------------- 1 | @using ServiceStack 2 | @using UserAuthProvider.ServiceStack.SelfHost.ServiceModel 3 | @inherits ServiceStack.Razor.ViewPage 4 | 5 | @{ 6 | ViewBag.Title = "ServiceStack Self Host with Razor"; 7 | } 8 | 9 |

Hello World Service

10 | 11 |

Access some secure content here!

-------------------------------------------------------------------------------- /src/test/IdentityServer3.Contrib.ServiceStack.Tests/ActAsUserGrantValidatorTests.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace IdentityServer3.Contrib.ServiceStack.Tests 5 | { 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.Collections.Specialized; 10 | using System.Security.Claims; 11 | using Core; 12 | using Core.Configuration; 13 | using Core.Models; 14 | using Core.Services.InMemory; 15 | using Core.Validation; 16 | using FakeItEasy; 17 | using FluentAssertions; 18 | using Xunit; 19 | 20 | public class ActAsUserGrantValidatorTests 21 | { 22 | [Fact] 23 | public void ValidateAsync_ReturnsInvalidRequestErrorWhenAccessTokenNotFound() 24 | { 25 | // Arrange 26 | var tokenRequest = new ValidatedTokenRequest { Raw = new NameValueCollection() }; 27 | var validator = new ActAsUserGrantValidator(null); 28 | 29 | // Act 30 | var result = validator.ValidateAsync(tokenRequest).Result; 31 | 32 | // Assert 33 | result.Error.Should().Be(Constants.TokenErrors.InvalidRequest); 34 | } 35 | 36 | [Fact] 37 | public void ValidateAsync_ReturnsInvalidRequestErrorWhenAccessTokenNotValid() 38 | { 39 | // Arrange 40 | var tokenRequest = new ValidatedTokenRequest { Raw = new NameValueCollection() }; 41 | tokenRequest.Raw.Add("access_token", "A12345"); 42 | tokenRequest.Raw.Add("client_referer", "http://localhost:12345"); 43 | 44 | var tokenValidatorFake = createTokenValidatorFake; 45 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)) 46 | .Returns(Task.FromResult(new TokenValidationResult { IsError = true })); 47 | 48 | var validator = new ActAsUserGrantValidator(tokenValidatorFake); 49 | 50 | // Act 51 | var result = validator.ValidateAsync(tokenRequest).Result; 52 | 53 | // Assert 54 | result.Error.Should().Be(Constants.TokenErrors.InvalidRequest); 55 | 56 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)).MustHaveHappened(); 57 | } 58 | 59 | [Fact] 60 | public void ValidateAsync_ReturnsInvalidRequestWhenClaimsNull() 61 | { 62 | // Arrange 63 | var tokenRequest = new ValidatedTokenRequest { Raw = new NameValueCollection() }; 64 | tokenRequest.Raw.Add("access_token", "A12345"); 65 | tokenRequest.Raw.Add("client_referer", "http://localhost:12345"); 66 | 67 | var tokenValidatorFake = createTokenValidatorFake; 68 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)) 69 | .Returns(Task.FromResult(new TokenValidationResult { IsError = false, Claims = null })); 70 | 71 | var validator = new ActAsUserGrantValidator(tokenValidatorFake); 72 | 73 | // Act 74 | var result = validator.ValidateAsync(tokenRequest).Result; 75 | 76 | // Assert 77 | result.Error.Should().Be(Constants.TokenErrors.InvalidRequest); 78 | 79 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)).MustHaveHappened(); 80 | } 81 | 82 | [Fact] 83 | public void ValidateAsync_ReturnsInvalidRequestWhenSubjectClaimNotFound() 84 | { 85 | // Arrange 86 | var tokenRequest = new ValidatedTokenRequest { Raw = new NameValueCollection() }; 87 | tokenRequest.Raw.Add("access_token", "A12345"); 88 | tokenRequest.Raw.Add("client_referer", "http://localhost:12345"); 89 | 90 | var tokenValidatorFake = createTokenValidatorFake; 91 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)) 92 | .Returns(Task.FromResult(new TokenValidationResult { IsError = false, Claims = new List() })); 93 | 94 | var validator = new ActAsUserGrantValidator(tokenValidatorFake); 95 | 96 | // Act 97 | var result = validator.ValidateAsync(tokenRequest).Result; 98 | 99 | // Assert 100 | result.Error.Should().Be(Constants.TokenErrors.InvalidRequest); 101 | 102 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)).MustHaveHappened(); 103 | } 104 | 105 | [Fact] 106 | public void ValidateAsync_ReturnsInvalidRequestWhenClientRefererDoesNotMatch() 107 | { 108 | // Arrange 109 | var tokenRequest = new ValidatedTokenRequest 110 | { 111 | Raw = new NameValueCollection(), 112 | Scopes = new List { "scope1", "scope2", "scope3" } 113 | }; 114 | tokenRequest.Raw.Add("access_token", "A12345"); 115 | tokenRequest.Raw.Add("client_referer", "http://localhost:12345"); 116 | 117 | var tokenValidatorFake = createTokenValidatorFake; 118 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)) 119 | .Returns(Task.FromResult(new TokenValidationResult 120 | { 121 | IsError = false, 122 | Claims = new List 123 | { 124 | new Claim(Constants.ClaimTypes.Subject, "sun123") 125 | }, 126 | Client = new Client { RedirectUris = new List { "http://piratebay:12345" } } 127 | })); 128 | 129 | var validator = new ActAsUserGrantValidator(tokenValidatorFake); 130 | 131 | // Act 132 | var result = validator.ValidateAsync(tokenRequest).Result; 133 | 134 | // Assert 135 | result.Error.Should().Be(Constants.TokenErrors.InvalidRequest); 136 | 137 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)).MustHaveHappened(); 138 | } 139 | 140 | [Fact] 141 | public void ValidateAsync_ReturnsResultWhenSubjectClaimFound() 142 | { 143 | // Arrange 144 | var tokenRequest = new ValidatedTokenRequest 145 | { 146 | Raw = new NameValueCollection(), 147 | Scopes = new List { "scope1", "scope2", "scope3" } 148 | }; 149 | tokenRequest.Raw.Add("access_token", "A12345"); 150 | tokenRequest.Raw.Add("client_referer", "http://localhost:12345"); 151 | 152 | var tokenValidatorFake = createTokenValidatorFake; 153 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)) 154 | .Returns(Task.FromResult(new TokenValidationResult 155 | { 156 | IsError = false, 157 | Claims = new List 158 | { 159 | new Claim(Constants.ClaimTypes.Subject, "sun123") 160 | }, 161 | Client = new Client { RedirectUris = new List { "http://localhost:12345" } } 162 | })); 163 | 164 | var validator = new ActAsUserGrantValidator(tokenValidatorFake); 165 | 166 | // Act 167 | var result = validator.ValidateAsync(tokenRequest).Result; 168 | 169 | // Assert 170 | result.Principal.Identity.AuthenticationType.Should().Be("access_token"); 171 | result.Principal.Claims.First().Type.Should().Be(Constants.ClaimTypes.Subject); 172 | result.Principal.Claims.First().Value.Should().Be("sun123"); 173 | 174 | A.CallTo(() => tokenValidatorFake.ValidateAccessTokenAsync("A12345", null)).MustHaveHappened(); 175 | } 176 | 177 | private readonly TokenValidator createTokenValidatorFake = A.Fake(x => x.WithArgumentsForConstructor(() => new TokenValidator(new IdentityServerOptions(), new InMemoryClientStore(null), new InMemoryTokenHandleStore(), null))); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/test/IdentityServer3.Contrib.ServiceStack.Tests/IdentityServer3.Contrib.ServiceStack.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net462 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/test/ServiceStack.Authentication.IdentityServer.Tests/IdentityServerAuthProviderAppSettingsExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Tests 5 | { 6 | using Configuration; 7 | using Enums; 8 | using Extensions; 9 | using FluentAssertions; 10 | using Xunit; 11 | 12 | public class IdentityServerAuthProviderAppSettingsExtensionsTests 13 | { 14 | [Fact] 15 | public void SetUserAuthProvider_SetsCorrectAuthProvider() 16 | { 17 | // Arrange 18 | var appSettings = new DictionarySettings(); 19 | 20 | // Act 21 | #pragma warning disable 618 22 | appSettings.SetUserAuthProvider(); 23 | #pragma warning restore 618 24 | 25 | // Assert 26 | appSettings.Get("oauth.provider") 27 | .Should() 28 | .Be(IdentityServerAuthProviderType.UserAuthProvider); 29 | } 30 | 31 | [Fact] 32 | public void SetImpersonationAuthProvider_SetsCorrectAuthProvider() 33 | { 34 | // Arrange 35 | var appSettings = new DictionarySettings(); 36 | 37 | // Act 38 | #pragma warning disable 618 39 | appSettings.SetImpersonationAuthProvider(); 40 | #pragma warning restore 618 41 | 42 | // Assert 43 | appSettings.Get("oauth.provider") 44 | .Should() 45 | .Be(IdentityServerAuthProviderType.ImpersonationProvider); 46 | } 47 | 48 | [Fact] 49 | public void SetServiceAuthProvider_SetsCorrectAuthProvider() 50 | { 51 | // Arrange 52 | var appSettings = new DictionarySettings(); 53 | 54 | // Act 55 | #pragma warning disable 618 56 | appSettings.SetServiceAuthProvider(); 57 | #pragma warning restore 618 58 | 59 | // Assert 60 | appSettings.Get("oauth.provider") 61 | .Should() 62 | .Be(IdentityServerAuthProviderType.ServiceProvider); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/ServiceStack.Authentication.IdentityServer.Tests/ServiceStack.Authentication.IdentityServer.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netcoreapp2.0 5 | ServiceStack.Authentication.IdentityServer.Tests 6 | ServiceStack.Authentication.IdentityServer.Tests 7 | true 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/test/ServiceStack.Authentication.IdentityServer.Tests/TestIdentityServerAuthProviderSettings.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Tests 5 | { 6 | using System.Collections.Generic; 7 | using Enums; 8 | using Interfaces; 9 | 10 | internal class TestIdentityServerAuthProviderSettings : IIdentityServerAuthProviderSettings 11 | { 12 | public string AuthRealm { get; set; } 13 | 14 | public string AuthorizeUrl { get; set; } 15 | 16 | public string IntrospectUrl { get; set; } 17 | 18 | public string UserInfoUrl { get; set; } 19 | 20 | public string RequestTokenUrl { get; set; } 21 | 22 | public string CallbackUrl { get; set; } 23 | 24 | public string ClientId { get; set; } 25 | 26 | public string ClientSecret { get; set; } 27 | 28 | public string JwksUrl { get; set; } 29 | 30 | public string Scopes { get; set; } 31 | 32 | public string Username { get; set; } 33 | 34 | public string Password { get; set; } 35 | 36 | public IList RoleClaimNames { get; set; } 37 | 38 | public IList PermissionClaimNames { get; set; } 39 | 40 | public IdentityServerOpenIdAuthorizationFlowType AuthorizationFlow { get; set; } 41 | 42 | public DocumentDiscoveryResult DiscoveryResult { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/ServiceStack.Authentication.IdentityServer.Tests/UserAuthProviderTests.cs: -------------------------------------------------------------------------------- 1 | // This Source Code Form is subject to the terms of the Mozilla Public 2 | // License, v. 2.0. If a copy of the MPL was not distributed with this 3 | // file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 | namespace ServiceStack.Authentication.IdentityServer.Tests 5 | { 6 | using Auth; 7 | using FakeItEasy; 8 | using FluentAssertions; 9 | using Providers; 10 | using Web; 11 | using Xunit; 12 | 13 | public class UserAuthProviderTests 14 | { 15 | [Theory] 16 | [InlineData(null)] 17 | [InlineData("http://localhost:5000/Auth/")] 18 | [InlineData("http://localhost:5001/Auth/IdentityServer")] 19 | public void IsInitialAuthenticateRequest_ReturnsFalseWhenAbsoluteUriIsNotValid(string absoluteUri) 20 | { 21 | // Arrange 22 | var httpRequestFake = A.Fake(); 23 | A.CallTo(() => httpRequestFake.AbsoluteUri).Returns(absoluteUri); 24 | 25 | var authTokensFake = A.Fake(); 26 | 27 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()) 28 | { 29 | CallbackUrl = "http://localhost:5000/Auth/IdentityServer" 30 | }; 31 | 32 | // Act 33 | var result = provider.IsInitialAuthenticateRequest(httpRequestFake, authTokensFake).Result; 34 | 35 | // Assert 36 | result.Should().Be(false); 37 | 38 | A.CallTo(() => httpRequestFake.AbsoluteUri).MustHaveHappened(); 39 | } 40 | 41 | [Theory] 42 | [InlineData(null)] 43 | [InlineData("")] 44 | public void IsInitialAuthenticateRequest_ReturnsTrueWhenValidUrlAndNoTokensFound(string accessToken) 45 | { 46 | // Arrange 47 | const string url = "http://localhost:5000/Auth/IdentityServer"; 48 | 49 | var httpRequestFake = A.Fake(); 50 | A.CallTo(() => httpRequestFake.AbsoluteUri).Returns(url); 51 | 52 | var authTokensFake = A.Fake(); 53 | A.CallTo(() => authTokensFake.AccessToken).Returns(accessToken); 54 | 55 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()) { CallbackUrl = url }; 56 | 57 | // Act 58 | var result = provider.IsInitialAuthenticateRequest(httpRequestFake, authTokensFake).Result; 59 | 60 | // Assert 61 | result.Should().Be(true); 62 | 63 | A.CallTo(() => httpRequestFake.AbsoluteUri).MustHaveHappened(); 64 | A.CallTo(() => authTokensFake.AccessToken).MustHaveHappened(); 65 | } 66 | 67 | [Fact] 68 | public void IsInitialAuthenticateRequest_ReturnsFalseWhenValidUrlAndHasAccessToken() 69 | { 70 | // Arrange 71 | const string url = "http://localhost:5000/Auth/IdentityServer"; 72 | const string accessToken = "A1234"; 73 | 74 | var httpRequestFake = A.Fake(); 75 | A.CallTo(() => httpRequestFake.AbsoluteUri).Returns(url); 76 | 77 | var authTokensFake = A.Fake(); 78 | A.CallTo(() => authTokensFake.AccessToken).Returns(accessToken); 79 | 80 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()) 81 | { 82 | CallbackUrl = url 83 | }; 84 | 85 | // Act 86 | var result = provider.IsInitialAuthenticateRequest(httpRequestFake, authTokensFake).Result; 87 | 88 | // Assert 89 | result.Should().Be(false); 90 | 91 | A.CallTo(() => httpRequestFake.AbsoluteUri).MustHaveHappened(); 92 | A.CallTo(() => authTokensFake.AccessToken).MustHaveHappened(); 93 | } 94 | 95 | [Fact] 96 | public void IsAuthorized_RequestNullSessionNull_ReturnsFalse() 97 | { 98 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()); 99 | 100 | // Act 101 | var result = provider.IsAuthorized(null, null); 102 | 103 | result.Should().Be(false); 104 | } 105 | 106 | [Fact] 107 | public void IsAuthorized_RequestNull_SessionNotAuthenticated_ReturnsFalse() 108 | { 109 | var authSessionFake = A.Fake(); 110 | var authTokenFake = A.Fake(); 111 | 112 | authSessionFake.IsAuthenticated = false; 113 | 114 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()); 115 | 116 | // Act 117 | var result = provider.IsAuthorized(authSessionFake, authTokenFake); 118 | 119 | result.Should().Be(false); 120 | } 121 | 122 | [Fact] 123 | public void IsAuthorized_RequestNull_SessionAuthenticated_AccessTokenNull_ReturnsFalse() 124 | { 125 | // Arrange 126 | var authSessionFake = A.Fake(); 127 | var authTokenFake = A.Fake(); 128 | 129 | authSessionFake.IsAuthenticated = true; 130 | authTokenFake.AccessToken = null; 131 | 132 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()); 133 | 134 | // Act 135 | var result = provider.IsAuthorized(authSessionFake, authTokenFake); 136 | 137 | // Assert 138 | result.Should().Be(false); 139 | } 140 | 141 | [Fact] 142 | public void IsAuthorized_RequestNull_SessionAuthenticated_AccessTokenValid_ReturnsTrue() 143 | { 144 | // Arrange 145 | var authSessionFake = A.Fake(); 146 | var authTokenFake = A.Fake(); 147 | 148 | authSessionFake.IsAuthenticated = true; 149 | authTokenFake.AccessToken = "A12345"; 150 | 151 | var provider = new UserAuthProvider(new TestIdentityServerAuthProviderSettings()); 152 | 153 | // Act 154 | var result = provider.IsAuthorized(authSessionFake, authTokenFake); 155 | 156 | result.Should().Be(true); 157 | } 158 | } 159 | } 160 | --------------------------------------------------------------------------------