├── .gitattributes
├── .gitignore
├── .travis.yml
├── AspNet.Security.OAuth.Extensions.sln
├── NuGet.config
├── README.md
├── build.cmd
├── build.ps1
├── build.sh
├── build
├── common.props
├── dependencies.props
├── key.snk
├── packages.props
├── repo.props
└── version.props
├── korebuild-lock.txt
├── korebuild.json
├── run.cmd
├── run.ps1
├── run.sh
├── src
├── AspNet.Security.OAuth.Introspection
│ ├── AspNet.Security.OAuth.Introspection.csproj
│ ├── Events
│ │ ├── ApplyChallengeContext.cs
│ │ ├── CreateTicketContext.cs
│ │ ├── RetrieveTokenContext.cs
│ │ ├── SendIntrospectionRequestContext.cs
│ │ └── ValidateTokenContext.cs
│ ├── OAuthIntrospectionConfiguration.cs
│ ├── OAuthIntrospectionConstants.cs
│ ├── OAuthIntrospectionDefaults.cs
│ ├── OAuthIntrospectionError.cs
│ ├── OAuthIntrospectionEvents.cs
│ ├── OAuthIntrospectionExtensions.cs
│ ├── OAuthIntrospectionFeature.cs
│ ├── OAuthIntrospectionHandler.cs
│ ├── OAuthIntrospectionHelpers.cs
│ ├── OAuthIntrospectionInitializer.cs
│ └── OAuthIntrospectionOptions.cs
├── AspNet.Security.OAuth.Validation
│ ├── AspNet.Security.OAuth.Validation.csproj
│ ├── Events
│ │ ├── ApplyChallengeContext.cs
│ │ ├── CreateTicketContext.cs
│ │ ├── DecryptTokenContext.cs
│ │ ├── RetrieveTokenContext.cs
│ │ └── ValidateTokenContext.cs
│ ├── OAuthValidationConstants.cs
│ ├── OAuthValidationDefaults.cs
│ ├── OAuthValidationError.cs
│ ├── OAuthValidationEvents.cs
│ ├── OAuthValidationExtensions.cs
│ ├── OAuthValidationFeature.cs
│ ├── OAuthValidationHandler.cs
│ ├── OAuthValidationHelpers.cs
│ ├── OAuthValidationInitializer.cs
│ └── OAuthValidationOptions.cs
├── Owin.Security.OAuth.Introspection
│ ├── Events
│ │ ├── ApplyChallengeContext.cs
│ │ ├── CreateTicketContext.cs
│ │ ├── RetrieveTokenContext.cs
│ │ ├── SendIntrospectionRequestContext.cs
│ │ └── ValidateTokenContext.cs
│ ├── OAuthIntrospectionConfiguration.cs
│ ├── OAuthIntrospectionConstants.cs
│ ├── OAuthIntrospectionDefaults.cs
│ ├── OAuthIntrospectionError.cs
│ ├── OAuthIntrospectionEvents.cs
│ ├── OAuthIntrospectionExtensions.cs
│ ├── OAuthIntrospectionHandler.cs
│ ├── OAuthIntrospectionHelpers.cs
│ ├── OAuthIntrospectionMiddleware.cs
│ ├── OAuthIntrospectionOptions.cs
│ └── Owin.Security.OAuth.Introspection.csproj
└── Owin.Security.OAuth.Validation
│ ├── Events
│ ├── ApplyChallengeContext.cs
│ ├── CreateTicketContext.cs
│ ├── DecryptTokenContext.cs
│ ├── RetrieveTokenContext.cs
│ └── ValidateTokenContext.cs
│ ├── OAuthValidationConstants.cs
│ ├── OAuthValidationDefaults.cs
│ ├── OAuthValidationError.cs
│ ├── OAuthValidationEvents.cs
│ ├── OAuthValidationExtensions.cs
│ ├── OAuthValidationHandler.cs
│ ├── OAuthValidationHelpers.cs
│ ├── OAuthValidationMiddleware.cs
│ ├── OAuthValidationOptions.cs
│ └── Owin.Security.OAuth.Validation.csproj
└── test
├── AspNet.Security.OAuth.Introspection.Tests
├── AspNet.Security.OAuth.Introspection.Tests.csproj
├── OAuthIntrospectionHandlerTests.cs
└── OAuthIntrospectionInitializerTests.cs
├── AspNet.Security.OAuth.Validation.Tests
├── AspNet.Security.OAuth.Validation.Tests.csproj
└── OAuthValidationHandlerTests.cs
├── Owin.Security.OAuth.Introspection.Tests
├── OAuthIntrospectionHandlerTests.cs
├── OAuthIntrospectionMiddlewareTests.cs
└── Owin.Security.OAuth.Introspection.Tests.csproj
└── Owin.Security.OAuth.Validation.Tests
├── OAuthValidationHandlerTests.cs
├── OAuthValidationMiddlewareTests.cs
└── Owin.Security.OAuth.Validation.Tests.csproj
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # VS 14 temporary folder
5 | *.sln.ide/
6 | target/
7 | .nuget/
8 | .vs/
9 | .build/
10 |
11 | # User-specific files
12 | *.suo
13 | *.user
14 | *.sln.docstates
15 | project.lock.json
16 |
17 | # Build results
18 |
19 | [Dd]ebug/
20 | [Rr]elease/
21 | x64/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
26 | !packages/*/build/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | *_i.c
33 | *_p.c
34 | *.ilk
35 | *.meta
36 | *.obj
37 | *.pch
38 | *.pdb
39 | *.pgc
40 | *.pgd
41 | *.rsp
42 | *.sbr
43 | *.tlb
44 | *.tli
45 | *.tlh
46 | *.tmp
47 | *.tmp_proj
48 | *.log
49 | *.vspscc
50 | *.vssscc
51 | .builds
52 | *.pidb
53 | *.log
54 | *.scc
55 |
56 | # Visual C++ cache files
57 | ipch/
58 | *.aps
59 | *.ncb
60 | *.opensdf
61 | *.sdf
62 | *.cachefile
63 |
64 | # Visual Studio profiler
65 | *.psess
66 | *.vsp
67 | *.vspx
68 |
69 | # Guidance Automation Toolkit
70 | *.gpState
71 |
72 | # ReSharper is a .NET coding add-in
73 | _ReSharper*/
74 | *.[Rr]e[Ss]harper
75 |
76 | # TeamCity is a build add-in
77 | _TeamCity*
78 |
79 | # DotCover is a Code Coverage Tool
80 | *.dotCover
81 |
82 | # NCrunch
83 | *.ncrunch*
84 | .*crunch*.local.xml
85 |
86 | # Installshield output folder
87 | [Ee]xpress/
88 |
89 | # DocProject is a documentation generator add-in
90 | DocProject/buildhelp/
91 | DocProject/Help/*.HxT
92 | DocProject/Help/*.HxC
93 | DocProject/Help/*.hhc
94 | DocProject/Help/*.hhk
95 | DocProject/Help/*.hhp
96 | DocProject/Help/Html2
97 | DocProject/Help/html
98 |
99 | # Click-Once directory
100 | publish/
101 |
102 | # Publish Web Output
103 | *.Publish.xml
104 |
105 | # NuGet Packages Directory
106 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
107 | packages/
108 |
109 | # Windows Azure Build Output
110 | csx
111 | *.build.csdef
112 |
113 | # Windows Store app package directory
114 | AppPackages/
115 |
116 | # Others
117 | sql/
118 | *.Cache
119 | ClientBin/
120 | [Ss]tyle[Cc]op.*
121 | ~$*
122 | *~
123 | *.dbmdl
124 | *.[Pp]ublish.xml
125 | *.publishsettings
126 |
127 | # RIA/Silverlight projects
128 | Generated_Code/
129 |
130 | # Backup & report files from converting an old project file to a newer
131 | # Visual Studio version. Backup files are not needed, because we have git ;-)
132 | _UpgradeReport_Files/
133 | Backup*/
134 | UpgradeLog*.XML
135 | UpgradeLog*.htm
136 |
137 | # SQL Server files
138 | *.mdf
139 | *.ldf
140 |
141 |
142 | #LightSwitch generated files
143 | GeneratedArtifacts/
144 | _Pvt_Extensions/
145 | ModelManifest.xml
146 |
147 | # =========================
148 | # Windows detritus
149 | # =========================
150 |
151 | # Windows image file caches
152 | Thumbs.db
153 | ehthumbs.db
154 |
155 | # Folder config file
156 | Desktop.ini
157 |
158 | # Recycle Bin used on file shares
159 | $RECYCLE.BIN/
160 |
161 | # Mac desktop service store files
162 | .DS_Store
163 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: csharp
2 | sudo: false
3 | dist: trusty
4 | addons:
5 | apt:
6 | packages:
7 | - gettext
8 | - libcurl4-openssl-dev
9 | - libicu-dev
10 | - libssl-dev
11 | - libunwind8
12 | - zlib1g
13 | env:
14 | global:
15 | - DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
16 | - DOTNET_CLI_TELEMETRY_OPTOUT: 1
17 | mono: none
18 | os:
19 | - linux
20 | - osx
21 | osx_image: xcode8.2
22 | before_install:
23 | - if test "$TRAVIS_OS_NAME" == "osx"; then brew update; brew install openssl; ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/; ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/; fi
24 | script:
25 | - ./build.sh
--------------------------------------------------------------------------------
/AspNet.Security.OAuth.Extensions.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.26228.4
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{2CFA7432-2FA7-4CF3-87DC-217C1363E11D}"
7 | ProjectSection(SolutionItems) = preProject
8 | build\common.props = build\common.props
9 | build\dependencies.props = build\dependencies.props
10 | build\key.snk = build\key.snk
11 | build\packages.props = build\packages.props
12 | build\repo.props = build\repo.props
13 | build\version.props = build\version.props
14 | EndProjectSection
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{7AADF737-9B13-4E5C-8F32-8BF21429E093}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{2B1B08E0-E9A3-40C0-B200-DE09952AF0E7}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Introspection", "src\AspNet.Security.OAuth.Introspection\AspNet.Security.OAuth.Introspection.csproj", "{A8569260-142C-427A-8B14-A8DF56CC15B7}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Introspection.Tests", "test\AspNet.Security.OAuth.Introspection.Tests\AspNet.Security.OAuth.Introspection.Tests.csproj", "{4070DC46-0FD5-4ADD-95B3-E9908AD82407}"
23 | EndProject
24 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Validation", "src\AspNet.Security.OAuth.Validation\AspNet.Security.OAuth.Validation.csproj", "{043FD757-9C69-4A68-93BF-EAD2672BBD78}"
25 | EndProject
26 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNet.Security.OAuth.Validation.Tests", "test\AspNet.Security.OAuth.Validation.Tests\AspNet.Security.OAuth.Validation.Tests.csproj", "{FC99E58D-86BC-4EAD-B282-C9F1491CCF96}"
27 | EndProject
28 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Owin.Security.OAuth.Introspection", "src\Owin.Security.OAuth.Introspection\Owin.Security.OAuth.Introspection.csproj", "{F9031F69-74BF-4321-88D5-2A606D3DA4E4}"
29 | EndProject
30 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Owin.Security.OAuth.Introspection.Tests", "test\Owin.Security.OAuth.Introspection.Tests\Owin.Security.OAuth.Introspection.Tests.csproj", "{A6B08CB3-0B3E-444D-BCF1-E9E41CEEC984}"
31 | EndProject
32 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Owin.Security.OAuth.Validation", "src\Owin.Security.OAuth.Validation\Owin.Security.OAuth.Validation.csproj", "{719AF040-773B-4DA5-B53E-28B26D1121FF}"
33 | EndProject
34 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Owin.Security.OAuth.Validation.Tests", "test\Owin.Security.OAuth.Validation.Tests\Owin.Security.OAuth.Validation.Tests.csproj", "{6DC60DCF-B34B-4F14-9E73-BE466059A9B2}"
35 | EndProject
36 | Global
37 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
38 | Debug|Any CPU = Debug|Any CPU
39 | Release|Any CPU = Release|Any CPU
40 | EndGlobalSection
41 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
42 | {A8569260-142C-427A-8B14-A8DF56CC15B7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {A8569260-142C-427A-8B14-A8DF56CC15B7}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {A8569260-142C-427A-8B14-A8DF56CC15B7}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {A8569260-142C-427A-8B14-A8DF56CC15B7}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {4070DC46-0FD5-4ADD-95B3-E9908AD82407}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {4070DC46-0FD5-4ADD-95B3-E9908AD82407}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {4070DC46-0FD5-4ADD-95B3-E9908AD82407}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {4070DC46-0FD5-4ADD-95B3-E9908AD82407}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {043FD757-9C69-4A68-93BF-EAD2672BBD78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {043FD757-9C69-4A68-93BF-EAD2672BBD78}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {043FD757-9C69-4A68-93BF-EAD2672BBD78}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {043FD757-9C69-4A68-93BF-EAD2672BBD78}.Release|Any CPU.Build.0 = Release|Any CPU
54 | {FC99E58D-86BC-4EAD-B282-C9F1491CCF96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 | {FC99E58D-86BC-4EAD-B282-C9F1491CCF96}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 | {FC99E58D-86BC-4EAD-B282-C9F1491CCF96}.Release|Any CPU.ActiveCfg = Release|Any CPU
57 | {FC99E58D-86BC-4EAD-B282-C9F1491CCF96}.Release|Any CPU.Build.0 = Release|Any CPU
58 | {F9031F69-74BF-4321-88D5-2A606D3DA4E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
59 | {F9031F69-74BF-4321-88D5-2A606D3DA4E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
60 | {F9031F69-74BF-4321-88D5-2A606D3DA4E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 | {F9031F69-74BF-4321-88D5-2A606D3DA4E4}.Release|Any CPU.Build.0 = Release|Any CPU
62 | {A6B08CB3-0B3E-444D-BCF1-E9E41CEEC984}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
63 | {A6B08CB3-0B3E-444D-BCF1-E9E41CEEC984}.Debug|Any CPU.Build.0 = Debug|Any CPU
64 | {A6B08CB3-0B3E-444D-BCF1-E9E41CEEC984}.Release|Any CPU.ActiveCfg = Release|Any CPU
65 | {A6B08CB3-0B3E-444D-BCF1-E9E41CEEC984}.Release|Any CPU.Build.0 = Release|Any CPU
66 | {719AF040-773B-4DA5-B53E-28B26D1121FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
67 | {719AF040-773B-4DA5-B53E-28B26D1121FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
68 | {719AF040-773B-4DA5-B53E-28B26D1121FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
69 | {719AF040-773B-4DA5-B53E-28B26D1121FF}.Release|Any CPU.Build.0 = Release|Any CPU
70 | {6DC60DCF-B34B-4F14-9E73-BE466059A9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
71 | {6DC60DCF-B34B-4F14-9E73-BE466059A9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
72 | {6DC60DCF-B34B-4F14-9E73-BE466059A9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
73 | {6DC60DCF-B34B-4F14-9E73-BE466059A9B2}.Release|Any CPU.Build.0 = Release|Any CPU
74 | EndGlobalSection
75 | GlobalSection(SolutionProperties) = preSolution
76 | HideSolutionNode = FALSE
77 | EndGlobalSection
78 | GlobalSection(NestedProjects) = preSolution
79 | {A8569260-142C-427A-8B14-A8DF56CC15B7} = {7AADF737-9B13-4E5C-8F32-8BF21429E093}
80 | {4070DC46-0FD5-4ADD-95B3-E9908AD82407} = {2B1B08E0-E9A3-40C0-B200-DE09952AF0E7}
81 | {043FD757-9C69-4A68-93BF-EAD2672BBD78} = {7AADF737-9B13-4E5C-8F32-8BF21429E093}
82 | {FC99E58D-86BC-4EAD-B282-C9F1491CCF96} = {2B1B08E0-E9A3-40C0-B200-DE09952AF0E7}
83 | {F9031F69-74BF-4321-88D5-2A606D3DA4E4} = {7AADF737-9B13-4E5C-8F32-8BF21429E093}
84 | {A6B08CB3-0B3E-444D-BCF1-E9E41CEEC984} = {2B1B08E0-E9A3-40C0-B200-DE09952AF0E7}
85 | {719AF040-773B-4DA5-B53E-28B26D1121FF} = {7AADF737-9B13-4E5C-8F32-8BF21429E093}
86 | {6DC60DCF-B34B-4F14-9E73-BE466059A9B2} = {2B1B08E0-E9A3-40C0-B200-DE09952AF0E7}
87 | EndGlobalSection
88 | GlobalSection(ExtensibilityGlobals) = postSolution
89 | SolutionGuid = {7DD610CB-5D2D-4AEB-B5D3-4DEEB694AA36}
90 | EndGlobalSection
91 | EndGlobal
92 |
--------------------------------------------------------------------------------
/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | AspNet.Security.OAuth.Extensions
2 | ================================
3 |
4 | > :warning: **This project has been merged into OpenIddict. For more information, read [Introducing OpenIddict 3.0 beta1](https://kevinchalet.com/2020/06/11/introducing-openiddict-3-0-beta1/)**.
5 |
6 | **AspNet.Security.OAuth.Extensions** is a collection of **token validation middleware** for ASP.NET Core 1.0 and OWIN/Katana.
7 |
8 | **The latest nightly builds can be found on [MyGet](https://www.myget.org/gallery/aspnet-contrib)**.
9 |
10 | [](https://ci.appveyor.com/project/aspnet-contrib/aspnet-security-oauth-extensions/branch/release)
11 | [](https://travis-ci.org/aspnet-contrib/AspNet.Security.OAuth.Extensions)
12 |
13 | ## Get started
14 |
15 | ```csharp
16 | app.UseOAuthValidation(options =>
17 | {
18 | options.Audiences.Add("resource_server");
19 | });
20 | ```
21 |
22 | ```csharp
23 | app.UseOAuthIntrospection(options =>
24 | {
25 | options.Authority = new Uri("https://openid.yourapp.com/");
26 | options.Audiences.Add("resource_server");
27 | options.ClientId = "resource_server";
28 | options.ClientSecret = "875sqd4s5d748z78z7ds1ff8zz8814ff88ed8ea4z4zzd";
29 | });
30 | ```
31 |
32 | ## Support
33 |
34 | **Need help or wanna share your thoughts?** Don't hesitate to join us on Gitter or ask your question on StackOverflow:
35 |
36 | - **Gitter: [https://gitter.im/aspnet-contrib/AspNet.Security.OAuth.Extensions](https://gitter.im/aspnet-contrib/AspNet.Security.OAuth.Extensions)**
37 | - **StackOverflow: [https://stackoverflow.com/questions/tagged/aspnet-contrib](https://stackoverflow.com/questions/tagged/aspnet-contrib)**
38 |
39 | ## Contributors
40 |
41 | **AspNet.Security.OAuth.Extensions** is actively maintained by **[Kévin Chalet](https://github.com/kevinchalet)**. Contributions are welcome and can be submitted using pull requests.
42 |
43 | ## License
44 |
45 | This project is licensed under the **Apache License**. This means that you can use, modify and distribute it freely. See [http://www.apache.org/licenses/LICENSE-2.0.html](http://www.apache.org/licenses/LICENSE-2.0.html) for more details.
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' default-build %*; exit $LASTEXITCODE"
3 |
--------------------------------------------------------------------------------
/build.ps1:
--------------------------------------------------------------------------------
1 | $ErrorActionPreference = "Stop"
2 |
3 | function DownloadWithRetry([string] $url, [string] $downloadLocation, [int] $retries)
4 | {
5 | while($true)
6 | {
7 | try
8 | {
9 | Invoke-WebRequest $url -OutFile $downloadLocation
10 | break
11 | }
12 | catch
13 | {
14 | $exceptionMessage = $_.Exception.Message
15 | Write-Host "Failed to download '$url': $exceptionMessage"
16 | if ($retries -gt 0) {
17 | $retries--
18 | Write-Host "Waiting 10 seconds before retrying. Retries left: $retries"
19 | Start-Sleep -Seconds 10
20 |
21 | }
22 | else
23 | {
24 | $exception = $_.Exception
25 | throw $exception
26 | }
27 | }
28 | }
29 | }
30 |
31 | cd $PSScriptRoot
32 |
33 | $repoFolder = $PSScriptRoot
34 | $env:REPO_FOLDER = $repoFolder
35 |
36 | $koreBuildZip="https://github.com/aspnet/KoreBuild/archive/dev.zip"
37 | if ($env:KOREBUILD_ZIP)
38 | {
39 | $koreBuildZip=$env:KOREBUILD_ZIP
40 | }
41 |
42 | $buildFolder = ".build"
43 | $buildFile="$buildFolder\KoreBuild.ps1"
44 |
45 | if (!(Test-Path $buildFolder)) {
46 | Write-Host "Downloading KoreBuild from $koreBuildZip"
47 |
48 | $tempFolder=$env:TEMP + "\KoreBuild-" + [guid]::NewGuid()
49 | New-Item -Path "$tempFolder" -Type directory | Out-Null
50 |
51 | $localZipFile="$tempFolder\korebuild.zip"
52 |
53 | DownloadWithRetry -url $koreBuildZip -downloadLocation $localZipFile -retries 6
54 |
55 | Add-Type -AssemblyName System.IO.Compression.FileSystem
56 | [System.IO.Compression.ZipFile]::ExtractToDirectory($localZipFile, $tempFolder)
57 |
58 | New-Item -Path "$buildFolder" -Type directory | Out-Null
59 | copy-item "$tempFolder\**\build\*" $buildFolder -Recurse
60 |
61 | # Cleanup
62 | if (Test-Path $tempFolder) {
63 | Remove-Item -Recurse -Force $tempFolder
64 | }
65 | }
66 |
67 | &"$buildFile" @args
68 |
--------------------------------------------------------------------------------
/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
5 |
6 | # Call "sync" between "chmod" and execution to prevent "text file busy" error in Docker (aufs)
7 | chmod +x "$DIR/run.sh"; sync
8 | "$DIR/run.sh" default-build "$@"
9 |
--------------------------------------------------------------------------------
/build/common.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | latest
8 | $(NoWarn);CS1591
9 | true
10 | true
11 | portable
12 |
13 |
14 |
15 |
16 | <_GenerateBindingRedirectsIntermediateAppConfig>$(IntermediateOutputPath)$(TargetFileName).config
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/dependencies.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2.0.0
5 | 4.4.0
6 | 5.2.0-preview1-408290725
7 | 2.1.4
8 | 10.3.0
9 | 10.0.2
10 | 4.7.63
11 | 4.3.2
12 | 2.0.0
13 | 2.0.0
14 | 4.0.0-alpha1
15 | 2.0.0
16 | 15.3.0
17 | 2.3.1
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/build/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aspnet-contrib/AspNet.Security.OAuth.Extensions/a413b870fa15ade0fd0c1a215a42bbe5871de223/build/key.snk
--------------------------------------------------------------------------------
/build/packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | true
7 | $(MSBuildThisFileDirectory)key.snk
8 | true
9 | true
10 | true
11 | true
12 |
13 |
14 |
15 | aspnet-contrib
16 | https://avatars3.githubusercontent.com/u/7998081?s=64
17 | https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions
18 | http://www.apache.org/licenses/LICENSE-2.0.html
19 | git
20 | git://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/build/repo.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build/version.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2.0.0
5 | rtm
6 | $(VersionSuffix)-$(BuildNumber)
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/korebuild-lock.txt:
--------------------------------------------------------------------------------
1 | version:2.1.0-rtm-15783
2 | commithash:5fc2b2f607f542a2ffde11c19825e786fc1a3774
3 |
--------------------------------------------------------------------------------
/korebuild.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/release/2.1/tools/korebuild.schema.json",
3 | "channel": "release/2.1"
4 | }
5 |
--------------------------------------------------------------------------------
/run.cmd:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 | PowerShell -NoProfile -NoLogo -ExecutionPolicy unrestricted -Command "[System.Threading.Thread]::CurrentThread.CurrentCulture = ''; [System.Threading.Thread]::CurrentThread.CurrentUICulture = '';& '%~dp0run.ps1' %*; exit $LASTEXITCODE"
3 |
--------------------------------------------------------------------------------
/run.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env powershell
2 | #requires -version 4
3 |
4 | <#
5 | .SYNOPSIS
6 | Executes KoreBuild commands.
7 |
8 | .DESCRIPTION
9 | Downloads korebuild if required. Then executes the KoreBuild command. To see available commands, execute with `-Command help`.
10 |
11 | .PARAMETER Command
12 | The KoreBuild command to run.
13 |
14 | .PARAMETER Path
15 | The folder to build. Defaults to the folder containing this script.
16 |
17 | .PARAMETER Channel
18 | The channel of KoreBuild to download. Overrides the value from the config file.
19 |
20 | .PARAMETER DotNetHome
21 | The directory where .NET Core tools will be stored.
22 |
23 | .PARAMETER ToolsSource
24 | The base url where build tools can be downloaded. Overrides the value from the config file.
25 |
26 | .PARAMETER Update
27 | Updates KoreBuild to the latest version even if a lock file is present.
28 |
29 | .PARAMETER ConfigFile
30 | The path to the configuration file that stores values. Defaults to korebuild.json.
31 |
32 | .PARAMETER ToolsSourceSuffix
33 | The Suffix to append to the end of the ToolsSource. Useful for query strings in blob stores.
34 |
35 | .PARAMETER Arguments
36 | Arguments to be passed to the command
37 |
38 | .NOTES
39 | This function will create a file $PSScriptRoot/korebuild-lock.txt. This lock file can be committed to source, but does not have to be.
40 | When the lockfile is not present, KoreBuild will create one using latest available version from $Channel.
41 |
42 | The $ConfigFile is expected to be an JSON file. It is optional, and the configuration values in it are optional as well. Any options set
43 | in the file are overridden by command line parameters.
44 |
45 | .EXAMPLE
46 | Example config file:
47 | ```json
48 | {
49 | "$schema": "https://raw.githubusercontent.com/aspnet/BuildTools/dev/tools/korebuild.schema.json",
50 | "channel": "dev",
51 | "toolsSource": "https://aspnetcore.blob.core.windows.net/buildtools"
52 | }
53 | ```
54 | #>
55 | [CmdletBinding(PositionalBinding = $false)]
56 | param(
57 | [Parameter(Mandatory = $true, Position = 0)]
58 | [string]$Command,
59 | [string]$Path = $PSScriptRoot,
60 | [Alias('c')]
61 | [string]$Channel,
62 | [Alias('d')]
63 | [string]$DotNetHome,
64 | [Alias('s')]
65 | [string]$ToolsSource,
66 | [Alias('u')]
67 | [switch]$Update,
68 | [string]$ConfigFile,
69 | [string]$ToolsSourceSuffix,
70 | [Parameter(ValueFromRemainingArguments = $true)]
71 | [string[]]$Arguments
72 | )
73 |
74 | Set-StrictMode -Version 2
75 | $ErrorActionPreference = 'Stop'
76 |
77 | #
78 | # Functions
79 | #
80 |
81 | function Get-KoreBuild {
82 |
83 | $lockFile = Join-Path $Path 'korebuild-lock.txt'
84 |
85 | if (!(Test-Path $lockFile) -or $Update) {
86 | Get-RemoteFile "$ToolsSource/korebuild/channels/$Channel/latest.txt" $lockFile $ToolsSourceSuffix
87 | }
88 |
89 | $version = Get-Content $lockFile | Where-Object { $_ -like 'version:*' } | Select-Object -first 1
90 | if (!$version) {
91 | Write-Error "Failed to parse version from $lockFile. Expected a line that begins with 'version:'"
92 | }
93 | $version = $version.TrimStart('version:').Trim()
94 | $korebuildPath = Join-Paths $DotNetHome ('buildtools', 'korebuild', $version)
95 |
96 | if (!(Test-Path $korebuildPath)) {
97 | Write-Host -ForegroundColor Magenta "Downloading KoreBuild $version"
98 | New-Item -ItemType Directory -Path $korebuildPath | Out-Null
99 | $remotePath = "$ToolsSource/korebuild/artifacts/$version/korebuild.$version.zip"
100 |
101 | try {
102 | $tmpfile = Join-Path ([IO.Path]::GetTempPath()) "KoreBuild-$([guid]::NewGuid()).zip"
103 | Get-RemoteFile $remotePath $tmpfile $ToolsSourceSuffix
104 | if (Get-Command -Name 'Expand-Archive' -ErrorAction Ignore) {
105 | # Use built-in commands where possible as they are cross-plat compatible
106 | Expand-Archive -Path $tmpfile -DestinationPath $korebuildPath
107 | }
108 | else {
109 | # Fallback to old approach for old installations of PowerShell
110 | Add-Type -AssemblyName System.IO.Compression.FileSystem
111 | [System.IO.Compression.ZipFile]::ExtractToDirectory($tmpfile, $korebuildPath)
112 | }
113 | }
114 | catch {
115 | Remove-Item -Recurse -Force $korebuildPath -ErrorAction Ignore
116 | throw
117 | }
118 | finally {
119 | Remove-Item $tmpfile -ErrorAction Ignore
120 | }
121 | }
122 |
123 | return $korebuildPath
124 | }
125 |
126 | function Join-Paths([string]$path, [string[]]$childPaths) {
127 | $childPaths | ForEach-Object { $path = Join-Path $path $_ }
128 | return $path
129 | }
130 |
131 | function Get-RemoteFile([string]$RemotePath, [string]$LocalPath, [string]$RemoteSuffix) {
132 | if ($RemotePath -notlike 'http*') {
133 | Copy-Item $RemotePath $LocalPath
134 | return
135 | }
136 |
137 | $retries = 10
138 | while ($retries -gt 0) {
139 | $retries -= 1
140 | try {
141 | Invoke-WebRequest -UseBasicParsing -Uri $($RemotePath + $RemoteSuffix) -OutFile $LocalPath
142 | return
143 | }
144 | catch {
145 | Write-Verbose "Request failed. $retries retries remaining"
146 | }
147 | }
148 |
149 | Write-Error "Download failed: '$RemotePath'."
150 | }
151 |
152 | #
153 | # Main
154 | #
155 |
156 | # Load configuration or set defaults
157 |
158 | $Path = Resolve-Path $Path
159 | if (!$ConfigFile) { $ConfigFile = Join-Path $Path 'korebuild.json' }
160 |
161 | if (Test-Path $ConfigFile) {
162 | try {
163 | $config = Get-Content -Raw -Encoding UTF8 -Path $ConfigFile | ConvertFrom-Json
164 | if ($config) {
165 | if (!($Channel) -and (Get-Member -Name 'channel' -InputObject $config)) { [string] $Channel = $config.channel }
166 | if (!($ToolsSource) -and (Get-Member -Name 'toolsSource' -InputObject $config)) { [string] $ToolsSource = $config.toolsSource}
167 | }
168 | }
169 | catch {
170 | Write-Warning "$ConfigFile could not be read. Its settings will be ignored."
171 | Write-Warning $Error[0]
172 | }
173 | }
174 |
175 | if (!$DotNetHome) {
176 | $DotNetHome = if ($env:DOTNET_HOME) { $env:DOTNET_HOME } `
177 | elseif ($env:USERPROFILE) { Join-Path $env:USERPROFILE '.dotnet'} `
178 | elseif ($env:HOME) {Join-Path $env:HOME '.dotnet'}`
179 | else { Join-Path $PSScriptRoot '.dotnet'}
180 | }
181 |
182 | if (!$Channel) { $Channel = 'dev' }
183 | if (!$ToolsSource) { $ToolsSource = 'https://aspnetcore.blob.core.windows.net/buildtools' }
184 |
185 | # Execute
186 |
187 | $korebuildPath = Get-KoreBuild
188 | Import-Module -Force -Scope Local (Join-Path $korebuildPath 'KoreBuild.psd1')
189 |
190 | try {
191 | Set-KoreBuildSettings -ToolsSource $ToolsSource -DotNetHome $DotNetHome -RepoPath $Path -ConfigFile $ConfigFile
192 | Invoke-KoreBuildCommand $Command @Arguments
193 | }
194 | finally {
195 | Remove-Module 'KoreBuild' -ErrorAction Ignore
196 | }
197 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -euo pipefail
4 |
5 | #
6 | # variables
7 | #
8 |
9 | RESET="\033[0m"
10 | RED="\033[0;31m"
11 | YELLOW="\033[0;33m"
12 | MAGENTA="\033[0;95m"
13 | DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
14 | [ -z "${DOTNET_HOME:-}" ] && DOTNET_HOME="$HOME/.dotnet"
15 | verbose=false
16 | update=false
17 | repo_path="$DIR"
18 | channel=''
19 | tools_source=''
20 | tools_source_suffix=''
21 |
22 | #
23 | # Functions
24 | #
25 | __usage() {
26 | echo "Usage: $(basename "${BASH_SOURCE[0]}") command [options] [[--] ...]"
27 | echo ""
28 | echo "Arguments:"
29 | echo " command The command to be run."
30 | echo " ... Arguments passed to the command. Variable number of arguments allowed."
31 | echo ""
32 | echo "Options:"
33 | echo " --verbose Show verbose output."
34 | echo " -c|--channel The channel of KoreBuild to download. Overrides the value from the config file.."
35 | echo " --config-file The path to the configuration file that stores values. Defaults to korebuild.json."
36 | echo " -d|--dotnet-home The directory where .NET Core tools will be stored. Defaults to '\$DOTNET_HOME' or '\$HOME/.dotnet."
37 | echo " --path The directory to build. Defaults to the directory containing the script."
38 | echo " -s|--tools-source|-ToolsSource The base url where build tools can be downloaded. Overrides the value from the config file."
39 | echo " --tools-source-suffix|-ToolsSourceSuffix The suffix to append to tools-source. Useful for query strings."
40 | echo " -u|--update Update to the latest KoreBuild even if the lock file is present."
41 | echo ""
42 | echo "Description:"
43 | echo " This function will create a file \$DIR/korebuild-lock.txt. This lock file can be committed to source, but does not have to be."
44 | echo " When the lockfile is not present, KoreBuild will create one using latest available version from \$channel."
45 |
46 | if [[ "${1:-}" != '--no-exit' ]]; then
47 | exit 2
48 | fi
49 | }
50 |
51 | get_korebuild() {
52 | local version
53 | local lock_file="$repo_path/korebuild-lock.txt"
54 | if [ ! -f "$lock_file" ] || [ "$update" = true ]; then
55 | __get_remote_file "$tools_source/korebuild/channels/$channel/latest.txt" "$lock_file" "$tools_source_suffix"
56 | fi
57 | version="$(grep 'version:*' -m 1 "$lock_file")"
58 | if [[ "$version" == '' ]]; then
59 | __error "Failed to parse version from $lock_file. Expected a line that begins with 'version:'"
60 | return 1
61 | fi
62 | version="$(echo "${version#version:}" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')"
63 | local korebuild_path="$DOTNET_HOME/buildtools/korebuild/$version"
64 |
65 | {
66 | if [ ! -d "$korebuild_path" ]; then
67 | mkdir -p "$korebuild_path"
68 | local remote_path="$tools_source/korebuild/artifacts/$version/korebuild.$version.zip"
69 | tmpfile="$(mktemp)"
70 | echo -e "${MAGENTA}Downloading KoreBuild ${version}${RESET}"
71 | if __get_remote_file "$remote_path" "$tmpfile" "$tools_source_suffix"; then
72 | unzip -q -d "$korebuild_path" "$tmpfile"
73 | fi
74 | rm "$tmpfile" || true
75 | fi
76 |
77 | source "$korebuild_path/KoreBuild.sh"
78 | } || {
79 | if [ -d "$korebuild_path" ]; then
80 | echo "Cleaning up after failed installation"
81 | rm -rf "$korebuild_path" || true
82 | fi
83 | return 1
84 | }
85 | }
86 |
87 | __error() {
88 | echo -e "${RED}error: $*${RESET}" 1>&2
89 | }
90 |
91 | __warn() {
92 | echo -e "${YELLOW}warning: $*${RESET}"
93 | }
94 |
95 | __machine_has() {
96 | hash "$1" > /dev/null 2>&1
97 | return $?
98 | }
99 |
100 | __get_remote_file() {
101 | local remote_path=$1
102 | local local_path=$2
103 | local remote_path_suffix=$3
104 |
105 | if [[ "$remote_path" != 'http'* ]]; then
106 | cp "$remote_path" "$local_path"
107 | return 0
108 | fi
109 |
110 | local failed=false
111 | if __machine_has wget; then
112 | wget --tries 10 --quiet -O "$local_path" "${remote_path}${remote_path_suffix}" || failed=true
113 | else
114 | failed=true
115 | fi
116 |
117 | if [ "$failed" = true ] && __machine_has curl; then
118 | failed=false
119 | curl --retry 10 -sSL -f --create-dirs -o "$local_path" "${remote_path}${remote_path_suffix}" || failed=true
120 | fi
121 |
122 | if [ "$failed" = true ]; then
123 | __error "Download failed: $remote_path" 1>&2
124 | return 1
125 | fi
126 | }
127 |
128 | #
129 | # main
130 | #
131 |
132 | command="${1:-}"
133 | shift
134 |
135 | while [[ $# -gt 0 ]]; do
136 | case $1 in
137 | -\?|-h|--help)
138 | __usage --no-exit
139 | exit 0
140 | ;;
141 | -c|--channel|-Channel)
142 | shift
143 | channel="${1:-}"
144 | [ -z "$channel" ] && __usage
145 | ;;
146 | --config-file|-ConfigFile)
147 | shift
148 | config_file="${1:-}"
149 | [ -z "$config_file" ] && __usage
150 | if [ ! -f "$config_file" ]; then
151 | __error "Invalid value for --config-file. $config_file does not exist."
152 | exit 1
153 | fi
154 | ;;
155 | -d|--dotnet-home|-DotNetHome)
156 | shift
157 | DOTNET_HOME="${1:-}"
158 | [ -z "$DOTNET_HOME" ] && __usage
159 | ;;
160 | --path|-Path)
161 | shift
162 | repo_path="${1:-}"
163 | [ -z "$repo_path" ] && __usage
164 | ;;
165 | -s|--tools-source|-ToolsSource)
166 | shift
167 | tools_source="${1:-}"
168 | [ -z "$tools_source" ] && __usage
169 | ;;
170 | --tools-source-suffix|-ToolsSourceSuffix)
171 | shift
172 | tools_source_suffix="${1:-}"
173 | [ -z "$tools_source_suffix" ] && __usage
174 | ;;
175 | -u|--update|-Update)
176 | update=true
177 | ;;
178 | --verbose|-Verbose)
179 | verbose=true
180 | ;;
181 | --)
182 | shift
183 | break
184 | ;;
185 | *)
186 | break
187 | ;;
188 | esac
189 | shift
190 | done
191 |
192 | if ! __machine_has unzip; then
193 | __error 'Missing required command: unzip'
194 | exit 1
195 | fi
196 |
197 | if ! __machine_has curl && ! __machine_has wget; then
198 | __error 'Missing required command. Either wget or curl is required.'
199 | exit 1
200 | fi
201 |
202 | [ -z "${config_file:-}" ] && config_file="$repo_path/korebuild.json"
203 | if [ -f "$config_file" ]; then
204 | if __machine_has jq ; then
205 | if jq '.' "$config_file" >/dev/null ; then
206 | config_channel="$(jq -r 'select(.channel!=null) | .channel' "$config_file")"
207 | config_tools_source="$(jq -r 'select(.toolsSource!=null) | .toolsSource' "$config_file")"
208 | else
209 | __warn "$config_file is invalid JSON. Its settings will be ignored."
210 | fi
211 | elif __machine_has python ; then
212 | if python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'))" >/dev/null ; then
213 | config_channel="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['channel'] if 'channel' in obj else '')")"
214 | config_tools_source="$(python -c "import json,codecs;obj=json.load(codecs.open('$config_file', 'r', 'utf-8-sig'));print(obj['toolsSource'] if 'toolsSource' in obj else '')")"
215 | else
216 | __warn "$config_file is invalid JSON. Its settings will be ignored."
217 | fi
218 | else
219 | __warn 'Missing required command: jq or pyton. Could not parse the JSON file. Its settings will be ignored.'
220 | fi
221 |
222 | [ ! -z "${config_channel:-}" ] && channel="$config_channel"
223 | [ ! -z "${config_tools_source:-}" ] && tools_source="$config_tools_source"
224 | fi
225 |
226 | [ -z "$channel" ] && channel='dev'
227 | [ -z "$tools_source" ] && tools_source='https://aspnetcore.blob.core.windows.net/buildtools'
228 |
229 | get_korebuild
230 | set_korebuildsettings "$tools_source" "$DOTNET_HOME" "$repo_path" "$config_file"
231 | invoke_korebuild_command "$command" "$@"
232 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/AspNet.Security.OAuth.Introspection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | netstandard2.0
7 |
8 |
9 |
10 | OAuth2 introspection middleware for ASP.NET Core.
11 | Kévin Chalet
12 | aspnetcore;authentication;jwt;openidconnect;security
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/Events/ApplyChallengeContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Introspection
12 | {
13 | ///
14 | /// Allows customization of the challenge process.
15 | ///
16 | public class ApplyChallengeContext : PropertiesContext
17 | {
18 | public ApplyChallengeContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthIntrospectionOptions options,
22 | [NotNull] AuthenticationProperties properties)
23 | : base(context, scheme, options, properties)
24 | {
25 | }
26 |
27 | ///
28 | /// Gets or sets the "error" value returned to the caller as part
29 | /// of the WWW-Authenticate header. This property may be null when
30 | /// is set to false.
31 | ///
32 | public string Error { get; set; }
33 |
34 | ///
35 | /// Gets or sets the "error_description" value returned to the caller as part
36 | /// of the WWW-Authenticate header. This property may be null when
37 | /// is set to false.
38 | ///
39 | public string ErrorDescription { get; set; }
40 |
41 | ///
42 | /// Gets or sets the "error_uri" value returned to the caller as part of the
43 | /// WWW-Authenticate header. This property is always null unless explicitly set.
44 | ///
45 | public string ErrorUri { get; set; }
46 |
47 | ///
48 | /// Gets or sets the "realm" value returned to
49 | /// the caller as part of the WWW-Authenticate header.
50 | ///
51 | public string Realm { get; set; }
52 |
53 | ///
54 | /// Gets or sets the "scope" value returned to
55 | /// the caller as part of the WWW-Authenticate header.
56 | ///
57 | public string Scope { get; set; }
58 |
59 | ///
60 | /// Gets a boolean indicating if the operation was handled from user code.
61 | ///
62 | public bool Handled { get; private set; }
63 |
64 | ///
65 | /// Marks the operation as handled to prevent the default logic from being applied.
66 | ///
67 | public void HandleResponse() => Handled = true;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/Events/CreateTicketContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System.Security.Claims;
8 | using JetBrains.Annotations;
9 | using Microsoft.AspNetCore.Authentication;
10 | using Microsoft.AspNetCore.Http;
11 | using Newtonsoft.Json.Linq;
12 |
13 | namespace AspNet.Security.OAuth.Introspection
14 | {
15 | ///
16 | /// Allows interception of the AuthenticationTicket creation process.
17 | ///
18 | public class CreateTicketContext : ResultContext
19 | {
20 | public CreateTicketContext(
21 | [NotNull] HttpContext context,
22 | [NotNull] AuthenticationScheme scheme,
23 | [NotNull] OAuthIntrospectionOptions options,
24 | [NotNull] AuthenticationTicket ticket,
25 | [NotNull] JObject payload)
26 | : base(context, scheme, options)
27 | {
28 | Principal = ticket.Principal;
29 | Properties = ticket.Properties;
30 | Payload = payload;
31 | }
32 |
33 | ///
34 | /// Gets the identity containing the user claims.
35 | ///
36 | public ClaimsIdentity Identity => Principal?.Identity as ClaimsIdentity;
37 |
38 | ///
39 | /// Gets the payload extracted from the introspection response.
40 | ///
41 | public JObject Payload { get; }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/Events/RetrieveTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Introspection
12 | {
13 | ///
14 | /// Allows custom parsing of access tokens from requests.
15 | ///
16 | public class RetrieveTokenContext : ResultContext
17 | {
18 | public RetrieveTokenContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthIntrospectionOptions options)
22 | : base(context, scheme, options)
23 | {
24 | }
25 |
26 | ///
27 | /// Gets or sets the access token.
28 | ///
29 | public string Token { get; set; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/Events/SendIntrospectionRequestContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System.Net.Http;
8 | using JetBrains.Annotations;
9 | using Microsoft.AspNetCore.Authentication;
10 | using Microsoft.AspNetCore.Http;
11 |
12 | namespace AspNet.Security.OAuth.Introspection
13 | {
14 | ///
15 | /// Allows for custom handling of the call to the Authorization Server's Introspection endpoint.
16 | ///
17 | public class SendIntrospectionRequestContext : BaseContext
18 | {
19 | public SendIntrospectionRequestContext(
20 | [NotNull] HttpContext context,
21 | [NotNull] AuthenticationScheme scheme,
22 | [NotNull] OAuthIntrospectionOptions options,
23 | [NotNull] HttpRequestMessage request,
24 | [NotNull] string token)
25 | : base(context, scheme, options)
26 | {
27 | Request = request;
28 | Token = token;
29 | }
30 |
31 | ///
32 | /// An for use by the application to call the authorization server.
33 | ///
34 | public HttpClient Client => Options.HttpClient;
35 |
36 | ///
37 | /// Gets the HTTP request sent to the introspection endpoint.
38 | ///
39 | public new HttpRequestMessage Request { get; }
40 |
41 | ///
42 | /// Gets or sets the HTTP response returned by the introspection endpoint.
43 | ///
44 | public new HttpResponseMessage Response { get; set; }
45 |
46 | ///
47 | /// The access token parsed from the client request.
48 | ///
49 | public string Token { get; }
50 |
51 | ///
52 | /// Gets a boolean indicating if the operation was handled from user code.
53 | ///
54 | public bool Handled { get; private set; }
55 |
56 | ///
57 | /// Marks the operation as handled to prevent the default logic from being applied.
58 | ///
59 | public void HandleResponse() => Handled = true;
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/Events/ValidateTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Introspection
12 | {
13 | ///
14 | /// Allows customization of the token validation logic.
15 | ///
16 | public class ValidateTokenContext : ResultContext
17 | {
18 | public ValidateTokenContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthIntrospectionOptions options,
22 | [NotNull] AuthenticationTicket ticket)
23 | : base(context, scheme, options)
24 | {
25 | Principal = ticket.Principal;
26 | Properties = ticket.Properties;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionConfiguration.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 | using JetBrains.Annotations;
12 | using Microsoft.IdentityModel.Protocols;
13 | using Microsoft.IdentityModel.Protocols.OpenIdConnect;
14 | using Newtonsoft.Json;
15 |
16 | namespace AspNet.Security.OAuth.Introspection
17 | {
18 | ///
19 | /// Represents an OAuth2 introspection configuration.
20 | ///
21 | [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
22 | public class OAuthIntrospectionConfiguration : OpenIdConnectConfiguration
23 | {
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | public OAuthIntrospectionConfiguration()
28 | : base() { }
29 |
30 | ///
31 | /// Initializes a new instance of the class.
32 | ///
33 | /// The JSON payload used to initialize the current instance.
34 | public OAuthIntrospectionConfiguration([NotNull] string json)
35 | : base(json) { }
36 |
37 | ///
38 | /// Gets or sets the introspection endpoint address.
39 | ///
40 | [JsonProperty(
41 | DefaultValueHandling = DefaultValueHandling.Ignore,
42 | NullValueHandling = NullValueHandling.Ignore,
43 | PropertyName = OAuthIntrospectionConstants.Metadata.IntrospectionEndpoint)]
44 | public string IntrospectionEndpoint { get; set; }
45 |
46 | ///
47 | /// Gets the list of authentication methods supported by the introspection endpoint.
48 | ///
49 | [JsonProperty(
50 | DefaultValueHandling = DefaultValueHandling.Ignore,
51 | NullValueHandling = NullValueHandling.Ignore,
52 | PropertyName = OAuthIntrospectionConstants.Metadata.IntrospectionEndpointAuthMethodsSupported)]
53 | public ISet IntrospectionEndpointAuthMethodsSupported { get; } = new HashSet();
54 |
55 | ///
56 | /// Represents a configuration retriever able to deserialize
57 | /// instances.
58 | ///
59 | public class Retriever : IConfigurationRetriever
60 | {
61 | ///
62 | /// Retrieves the OAuth2 introspection configuration from the specified address.
63 | ///
64 | /// The address of the discovery document.
65 | /// The object used to retrieve the discovery document.
66 | /// The that can be used to abort the operation.
67 | /// An instance.
68 | public async Task GetConfigurationAsync(
69 | [NotNull] string address, [NotNull] IDocumentRetriever retriever, CancellationToken cancellationToken)
70 | {
71 | if (string.IsNullOrEmpty(address))
72 | {
73 | throw new ArgumentException("The address cannot be null or empty.", nameof(address));
74 | }
75 |
76 | if (retriever == null)
77 | {
78 | throw new ArgumentNullException(nameof(retriever));
79 | }
80 |
81 | return new OAuthIntrospectionConfiguration(await retriever.GetDocumentAsync(address, cancellationToken));
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionConstants.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Introspection
8 | {
9 | public static class OAuthIntrospectionConstants
10 | {
11 | public static class Claims
12 | {
13 | public const string Active = "active";
14 | public const string Audience = "aud";
15 | public const string ExpiresAt = "exp";
16 | public const string IssuedAt = "iat";
17 | public const string JwtId = "jti";
18 | public const string Name = "name";
19 | public const string NotBefore = "nbf";
20 | public const string Role = "role";
21 | public const string Scope = "scope";
22 | public const string Subject = "sub";
23 | public const string TokenType = "token_type";
24 | public const string TokenUsage = "token_usage";
25 | public const string Username = "username";
26 | }
27 |
28 | public static class ClaimValueTypes
29 | {
30 | public const string Json = "JSON";
31 | public const string JsonArray = "JSON_ARRAY";
32 | }
33 |
34 | public static class ClientAuthenticationMethods
35 | {
36 | public const string ClientSecretBasic = "client_secret_basic";
37 | public const string ClientSecretPost = "client_secret_post";
38 | }
39 |
40 | public static class Errors
41 | {
42 | public const string InsufficientScope = "insufficient_scope";
43 | public const string InvalidRequest = "invalid_request";
44 | public const string InvalidToken = "invalid_token";
45 | }
46 |
47 | public static class Metadata
48 | {
49 | public const string IntrospectionEndpoint = "introspection_endpoint";
50 | public const string IntrospectionEndpointAuthMethodsSupported = "introspection_endpoint_auth_methods_supported";
51 | }
52 |
53 | public static class Parameters
54 | {
55 | public const string ClientId = "client_id";
56 | public const string ClientSecret = "client_secret";
57 | public const string Error = "error";
58 | public const string ErrorDescription = "error_description";
59 | public const string ErrorUri = "error_uri";
60 | public const string Realm = "realm";
61 | public const string Scope = "scope";
62 | public const string Token = "token";
63 | public const string TokenTypeHint = "token_type_hint";
64 | }
65 |
66 | public static class Properties
67 | {
68 | public const string AccessToken = "access_token";
69 | public const string Audiences = ".audiences";
70 | public const string Error = ".error";
71 | public const string ErrorDescription = ".error_description";
72 | public const string ErrorUri = ".error_uri";
73 | public const string Realm = ".realm";
74 | public const string Scope = ".scope";
75 | public const string Scopes = ".scopes";
76 | public const string TokenId = ".token_id";
77 | public const string TokenUsage = ".token_usage";
78 | }
79 |
80 | public static class Schemes
81 | {
82 | public const string Basic = "Basic";
83 | public const string Bearer = "Bearer";
84 | }
85 |
86 | public static class Separators
87 | {
88 | public static readonly char[] Space = { ' ' };
89 | }
90 |
91 | public static class TokenTypeHints
92 | {
93 | public const string AccessToken = "access_token";
94 | }
95 |
96 | public static class TokenUsages
97 | {
98 | public const string AccessToken = "access_token";
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionDefaults.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Introspection
8 | {
9 | public static class OAuthIntrospectionDefaults
10 | {
11 | ///
12 | /// Gets the default scheme used by the introspection middleware.
13 | ///
14 | public const string AuthenticationScheme = "Bearer";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionError.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Introspection
8 | {
9 | ///
10 | /// Represents an OAuth2 introspection error.
11 | ///
12 | public class OAuthIntrospectionError
13 | {
14 | ///
15 | /// Gets or sets the error code.
16 | ///
17 | public string Error { get; set; }
18 |
19 | ///
20 | /// Gets or sets the error_description.
21 | ///
22 | public string ErrorDescription { get; set; }
23 |
24 | ///
25 | /// Gets or sets the error_uri.
26 | ///
27 | public string ErrorUri { get; set; }
28 |
29 | ///
30 | /// Gets or sets the realm.
31 | ///
32 | public string Realm { get; set; }
33 |
34 | ///
35 | /// Gets or sets the scope.
36 | ///
37 | public string Scope { get; set; }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionEvents.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Threading.Tasks;
9 |
10 | namespace AspNet.Security.OAuth.Introspection
11 | {
12 | ///
13 | /// Allows customization of introspection handling within the middleware.
14 | ///
15 | public class OAuthIntrospectionEvents
16 | {
17 | ///
18 | /// Invoked when a challenge response is returned to the caller.
19 | ///
20 | public Func OnApplyChallenge { get; set; } = context => Task.CompletedTask;
21 |
22 | ///
23 | /// Invoked when a ticket is to be created from an introspection response.
24 | ///
25 | public Func OnCreateTicket { get; set; } = context => Task.CompletedTask;
26 |
27 | ///
28 | /// Invoked when a token is to be sent to the authorization server for introspection.
29 | ///
30 | public Func OnSendIntrospectionRequest { get; set; } = context => Task.CompletedTask;
31 |
32 | ///
33 | /// Invoked when a token is to be parsed from a newly-received request.
34 | ///
35 | public Func OnRetrieveToken { get; set; } = context => Task.CompletedTask;
36 |
37 | ///
38 | /// Invoked when a token is to be validated, before final processing.
39 | ///
40 | public Func OnValidateToken { get; set; } = context => Task.CompletedTask;
41 |
42 | ///
43 | /// Invoked when a challenge response is returned to the caller.
44 | ///
45 | public virtual Task ApplyChallenge(ApplyChallengeContext context) => OnApplyChallenge(context);
46 |
47 | ///
48 | /// Invoked when a ticket is to be created from an introspection response.
49 | ///
50 | public virtual Task CreateTicket(CreateTicketContext context) => OnCreateTicket(context);
51 |
52 | ///
53 | /// Invoked when a token is to be sent to the authorization server for introspection.
54 | ///
55 | public virtual Task SendIntrospectionRequest(SendIntrospectionRequestContext context) => OnSendIntrospectionRequest(context);
56 |
57 | ///
58 | /// Invoked when a token is to be parsed from a newly-received request.
59 | ///
60 | public virtual Task RetrieveToken(RetrieveTokenContext context) => OnRetrieveToken(context);
61 |
62 | ///
63 | /// Invoked when a token is to be validated, before final processing.
64 | ///
65 | public virtual Task ValidateToken(ValidateTokenContext context) => OnValidateToken(context);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionExtensions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using AspNet.Security.OAuth.Introspection;
10 | using JetBrains.Annotations;
11 | using Microsoft.AspNetCore.Authentication;
12 | using Microsoft.Extensions.DependencyInjection.Extensions;
13 | using Microsoft.Extensions.Options;
14 |
15 | namespace Microsoft.Extensions.DependencyInjection
16 | {
17 | ///
18 | /// Provides extension methods used to configure the OAuth2
19 | /// introspection middleware in an ASP.NET Core pipeline.
20 | ///
21 | public static class OAuthIntrospectionExtensions
22 | {
23 | ///
24 | /// Adds a new instance of the OAuth2 introspection middleware in the ASP.NET Core pipeline.
25 | ///
26 | /// The authentication builder.
27 | /// The authentication builder.
28 | public static AuthenticationBuilder AddOAuthIntrospection([NotNull] this AuthenticationBuilder builder)
29 | {
30 | return builder.AddOAuthIntrospection(OAuthIntrospectionDefaults.AuthenticationScheme);
31 | }
32 |
33 | ///
34 | /// Adds a new instance of the OAuth2 introspection middleware in the ASP.NET Core pipeline.
35 | ///
36 | /// The authentication builder.
37 | /// The delegate used to configure the introspection options.
38 | /// The authentication builder.
39 | public static AuthenticationBuilder AddOAuthIntrospection(
40 | [NotNull] this AuthenticationBuilder builder,
41 | [NotNull] Action configuration)
42 | {
43 | return builder.AddOAuthIntrospection(OAuthIntrospectionDefaults.AuthenticationScheme, configuration);
44 | }
45 |
46 | ///
47 | /// Adds a new instance of the OAuth2 introspection middleware in the ASP.NET Core pipeline.
48 | ///
49 | /// The authentication builder.
50 | /// The authentication scheme associated with this instance.
51 | /// The authentication builder.
52 | [EditorBrowsable(EditorBrowsableState.Advanced)]
53 | public static AuthenticationBuilder AddOAuthIntrospection(
54 | [NotNull] this AuthenticationBuilder builder, [NotNull] string scheme)
55 | {
56 | return builder.AddOAuthIntrospection(scheme, options => { });
57 | }
58 |
59 | ///
60 | /// Adds a new instance of the OAuth2 introspection middleware in the ASP.NET Core pipeline.
61 | ///
62 | /// The authentication builder.
63 | /// The authentication scheme associated with this instance.
64 | /// The delegate used to configure the introspection options.
65 | /// The authentication builder.
66 | [EditorBrowsable(EditorBrowsableState.Advanced)]
67 | public static AuthenticationBuilder AddOAuthIntrospection(
68 | [NotNull] this AuthenticationBuilder builder, [NotNull] string scheme,
69 | [NotNull] Action configuration)
70 | {
71 | if (builder == null)
72 | {
73 | throw new ArgumentNullException(nameof(builder));
74 | }
75 |
76 | if (configuration == null)
77 | {
78 | throw new ArgumentNullException(nameof(configuration));
79 | }
80 |
81 | if (string.IsNullOrEmpty(scheme))
82 | {
83 | throw new ArgumentException("The scheme cannot be null or empty.", nameof(scheme));
84 | }
85 |
86 | // Note: TryAddEnumerable() is used here to ensure the initializer is only registered once.
87 | builder.Services.TryAddEnumerable(
88 | ServiceDescriptor.Singleton,
89 | OAuthIntrospectionInitializer>());
90 |
91 | return builder.AddScheme(scheme, configuration);
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionFeature.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Introspection
8 | {
9 | ///
10 | /// Exposes the OAuth2 introspection details
11 | /// associated with the current request.
12 | ///
13 | public class OAuthIntrospectionFeature
14 | {
15 | ///
16 | /// Gets or sets the error details returned
17 | /// as part of the challenge response.
18 | ///
19 | public OAuthIntrospectionError Error { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionHelpers.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using JetBrains.Annotations;
9 | using Microsoft.AspNetCore.Authentication;
10 |
11 | namespace AspNet.Security.OAuth.Introspection
12 | {
13 | ///
14 | /// Defines a set of commonly used helpers.
15 | ///
16 | internal static class OAuthIntrospectionHelpers
17 | {
18 | ///
19 | /// Gets a given property from the authentication properties.
20 | ///
21 | /// The authentication properties.
22 | /// The specific property to look for.
23 | /// The value corresponding to the property, or null if the property cannot be found.
24 | public static string GetProperty([NotNull] this AuthenticationProperties properties, [NotNull] string property)
25 | {
26 | if (properties == null)
27 | {
28 | throw new ArgumentNullException(nameof(properties));
29 | }
30 |
31 | if (string.IsNullOrEmpty(property))
32 | {
33 | throw new ArgumentException("The property name cannot be null or empty.", nameof(property));
34 | }
35 |
36 | if (!properties.Items.TryGetValue(property, out string value))
37 | {
38 | return null;
39 | }
40 |
41 | return value;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionInitializer.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using System.Net.Http;
10 | using JetBrains.Annotations;
11 | using Microsoft.AspNetCore.Authentication;
12 | using Microsoft.AspNetCore.DataProtection;
13 | using Microsoft.Extensions.Caching.Distributed;
14 | using Microsoft.Extensions.Options;
15 | using Microsoft.IdentityModel.Protocols;
16 |
17 | namespace AspNet.Security.OAuth.Introspection
18 | {
19 | ///
20 | /// Contains the methods required to ensure that the configuration used by
21 | /// the OAuth2 introspection handler is in a consistent and valid state.
22 | ///
23 | [EditorBrowsable(EditorBrowsableState.Never)]
24 | public class OAuthIntrospectionInitializer : IPostConfigureOptions
25 | {
26 | private readonly IDistributedCache _cache;
27 | private readonly IDataProtectionProvider _dataProtectionProvider;
28 |
29 | ///
30 | /// Creates a new instance of the class.
31 | ///
32 | public OAuthIntrospectionInitializer(
33 | [NotNull] IDistributedCache cache,
34 | [NotNull] IDataProtectionProvider dataProtectionProvider)
35 | {
36 | _cache = cache;
37 | _dataProtectionProvider = dataProtectionProvider;
38 | }
39 |
40 | ///
41 | /// Populates the default OAuth2 introspection options and ensure
42 | /// that the configuration is in a consistent and valid state.
43 | ///
44 | /// The authentication scheme associated with the handler instance.
45 | /// The options instance to initialize.
46 | public void PostConfigure([NotNull] string name, [NotNull] OAuthIntrospectionOptions options)
47 | {
48 | if (options == null)
49 | {
50 | throw new ArgumentNullException(nameof(options));
51 | }
52 |
53 | if (string.IsNullOrEmpty(name))
54 | {
55 | throw new ArgumentException("The options instance name cannot be null or empty.", nameof(name));
56 | }
57 |
58 | if (string.IsNullOrEmpty(options.ClientId) || string.IsNullOrEmpty(options.ClientSecret))
59 | {
60 | throw new InvalidOperationException("Client credentials must be configured.");
61 | }
62 |
63 | if (options.Events == null)
64 | {
65 | options.Events = new OAuthIntrospectionEvents();
66 | }
67 |
68 | if (options.DataProtectionProvider == null)
69 | {
70 | options.DataProtectionProvider = _dataProtectionProvider;
71 | }
72 |
73 | if (options.AccessTokenFormat == null)
74 | {
75 | var protector = options.DataProtectionProvider.CreateProtector(
76 | nameof(OAuthIntrospectionHandler),
77 | nameof(options.AccessTokenFormat), name);
78 |
79 | options.AccessTokenFormat = new TicketDataFormat(protector);
80 | }
81 |
82 | if (options.Cache == null)
83 | {
84 | options.Cache = _cache;
85 | }
86 |
87 | if (options.HttpClient == null)
88 | {
89 | options.HttpClient = new HttpClient
90 | {
91 | Timeout = TimeSpan.FromSeconds(15),
92 | MaxResponseContentBufferSize = 1024 * 1024 * 10
93 | };
94 |
95 | options.HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd("ASP.NET Core OAuth2 introspection middleware");
96 | }
97 |
98 | if (options.ConfigurationManager == null)
99 | {
100 | if (options.Configuration != null)
101 | {
102 | if (string.IsNullOrEmpty(options.Configuration.IntrospectionEndpoint))
103 | {
104 | throw new InvalidOperationException("The introspection endpoint address cannot be null or empty.");
105 | }
106 |
107 | options.ConfigurationManager = new StaticConfigurationManager(options.Configuration);
108 | }
109 |
110 | else
111 | {
112 | if (options.Authority == null && options.MetadataAddress == null)
113 | {
114 | throw new InvalidOperationException("The authority or an absolute metadata endpoint address must be provided.");
115 | }
116 |
117 | if (options.MetadataAddress == null)
118 | {
119 | options.MetadataAddress = new Uri(".well-known/openid-configuration", UriKind.Relative);
120 | }
121 |
122 | if (!options.MetadataAddress.IsAbsoluteUri)
123 | {
124 | if (options.Authority == null || !options.Authority.IsAbsoluteUri)
125 | {
126 | throw new InvalidOperationException("The authority must be provided and must be an absolute URL.");
127 | }
128 |
129 | if (!string.IsNullOrEmpty(options.Authority.Fragment) || !string.IsNullOrEmpty(options.Authority.Query))
130 | {
131 | throw new InvalidOperationException("The authority cannot contain a fragment or a query string.");
132 | }
133 |
134 | if (!options.Authority.OriginalString.EndsWith("/"))
135 | {
136 | options.Authority = new Uri(options.Authority.OriginalString + "/", UriKind.Absolute);
137 | }
138 |
139 | options.MetadataAddress = new Uri(options.Authority, options.MetadataAddress);
140 | }
141 |
142 | if (options.RequireHttpsMetadata && !options.MetadataAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
143 | {
144 | throw new InvalidOperationException("The metadata endpoint address must be a HTTPS URL when " +
145 | "'RequireHttpsMetadata' is not set to 'false'.");
146 | }
147 |
148 | options.ConfigurationManager = new ConfigurationManager(
149 | options.MetadataAddress.AbsoluteUri, new OAuthIntrospectionConfiguration.Retriever(),
150 | new HttpDocumentRetriever(options.HttpClient) { RequireHttps = options.RequireHttpsMetadata });
151 | }
152 | }
153 | }
154 | }
155 | }
156 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Introspection/OAuthIntrospectionOptions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Net.Http;
10 | using Microsoft.AspNetCore.Authentication;
11 | using Microsoft.AspNetCore.DataProtection;
12 | using Microsoft.Extensions.Caching.Distributed;
13 | using Microsoft.IdentityModel.Protocols;
14 |
15 | namespace AspNet.Security.OAuth.Introspection
16 | {
17 | ///
18 | /// Exposes various settings needed to control
19 | /// the behavior of the introspection middleware.
20 | ///
21 | public class OAuthIntrospectionOptions : AuthenticationSchemeOptions
22 | {
23 | ///
24 | /// Creates a new instance of the class.
25 | ///
26 | public OAuthIntrospectionOptions()
27 | {
28 | Events = new OAuthIntrospectionEvents();
29 | }
30 |
31 | ///
32 | /// Gets the intended audiences of this resource server.
33 | /// Setting this property is recommended when the authorization
34 | /// server issues access tokens for multiple distinct resource servers.
35 | ///
36 | public ISet Audiences { get; } = new HashSet(StringComparer.Ordinal);
37 |
38 | ///
39 | /// Gets or sets the absolute URL of the OAuth2/OpenID Connect server.
40 | /// Note: this property is ignored when
41 | /// or are set.
42 | ///
43 | public Uri Authority { get; set; }
44 |
45 | ///
46 | /// Gets or sets the URL of the OAuth2/OpenID Connect server discovery endpoint.
47 | /// When the URL is relative, must be set and absolute.
48 | /// Note: this property is ignored when
49 | /// or are set.
50 | ///
51 | public Uri MetadataAddress { get; set; }
52 |
53 | ///
54 | /// Gets or sets a boolean indicating whether HTTPS is required to retrieve the metadata document.
55 | /// The default value is true. This option should be used only in development environments.
56 | /// Note: this property is ignored when or are set.
57 | ///
58 | public bool RequireHttpsMetadata { get; set; } = true;
59 |
60 | ///
61 | /// Gets or sets the configuration used by the introspection middleware.
62 | /// Note: this property is ignored when is set.
63 | ///
64 | public OAuthIntrospectionConfiguration Configuration { get; set; }
65 |
66 | ///
67 | /// Gets or sets the configuration manager used by the introspection middleware.
68 | ///
69 | public IConfigurationManager ConfigurationManager { get; set; }
70 |
71 | ///
72 | /// Gets or sets the client identifier representing the resource server.
73 | ///
74 | public string ClientId { get; set; }
75 |
76 | ///
77 | /// Gets or sets the client secret used to
78 | /// communicate with the introspection endpoint.
79 | ///
80 | public string ClientSecret { get; set; }
81 |
82 | ///
83 | /// Gets or sets the optional "realm" value returned to
84 | /// the caller as part of the WWW-Authenticate header.
85 | ///
86 | public string Realm { get; set; }
87 |
88 | ///
89 | /// Gets or sets a boolean determining whether the access token should be stored in the
90 | /// after a successful authentication process.
91 | ///
92 | public bool SaveToken { get; set; } = true;
93 |
94 | ///
95 | /// Gets or sets a boolean determining whether the token validation errors should be returned to the caller.
96 | /// Enabled by default, this option can be disabled to prevent the introspection middleware from returning
97 | /// an error, an error_description and/or an error_uri in the WWW-Authenticate header.
98 | ///
99 | public bool IncludeErrorDetails { get; set; } = true;
100 |
101 | ///
102 | /// Gets or sets the claim type used for the name claim.
103 | /// By default, the standard
104 | /// claim defined by the OAuth2 introspection specification is used.
105 | ///
106 | public string NameClaimType { get; set; } = OAuthIntrospectionConstants.Claims.Name;
107 |
108 | ///
109 | /// Gets or sets the claim type used for the role claim(s).
110 | /// By default, is used.
111 | ///
112 | public string RoleClaimType { get; set; } = OAuthIntrospectionConstants.Claims.Role;
113 |
114 | ///
115 | /// Gets or sets the cache used to store the access tokens/authentication tickets
116 | /// and the introspection responses returned received by the resource server.
117 | ///
118 | public IDistributedCache Cache { get; set; }
119 |
120 | ///
121 | /// Gets or sets the caching policy used to determine
122 | /// how long the introspection responses should be cached.
123 | /// Note: this property can be set to null to
124 | /// prevent the introspection responses from being cached.
125 | ///
126 | public DistributedCacheEntryOptions CachingPolicy { get; set; } = new DistributedCacheEntryOptions
127 | {
128 | AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
129 | };
130 |
131 | ///
132 | /// Gets or sets the object provided by the application to process events raised by the authentication middleware.
133 | /// The application may implement the interface fully, or it may create an instance of
134 | /// and assign delegates only to the events it wants to process.
135 | ///
136 | public new OAuthIntrospectionEvents Events
137 | {
138 | get => (OAuthIntrospectionEvents) base.Events;
139 | set => base.Events = value;
140 | }
141 |
142 | ///
143 | /// Gets or sets the HTTP client used to communicate with the remote OAuth2 server.
144 | ///
145 | public HttpClient HttpClient { get; set; }
146 |
147 | ///
148 | /// Gets or sets the clock used to determine the current date/time.
149 | ///
150 | public ISystemClock SystemClock { get; set; } = new SystemClock();
151 |
152 | ///
153 | /// Gets or sets the data format used to serialize and deserialize
154 | /// the authenticated tickets stored in the distributed cache.
155 | ///
156 | public ISecureDataFormat AccessTokenFormat { get; set; }
157 |
158 | ///
159 | /// Gets or sets the data protection provider used to create the default
160 | /// data protectors used by the OAuth2 introspection handler.
161 | /// When this property is set to null, the data protection provider
162 | /// is directly retrieved from the dependency injection container.
163 | ///
164 | public IDataProtectionProvider DataProtectionProvider { get; set; }
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/AspNet.Security.OAuth.Validation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | netstandard2.0
7 |
8 |
9 |
10 | OAuth2 validation middleware for ASP.NET Core.
11 | Kévin Chalet
12 | aspnetcore;authentication;jwt;openidconnect;security
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/Events/ApplyChallengeContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Validation
12 | {
13 | ///
14 | /// Allows customization of the challenge process.
15 | ///
16 | public class ApplyChallengeContext : PropertiesContext
17 | {
18 | public ApplyChallengeContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] AuthenticationProperties properties)
23 | : base(context, scheme, options, properties)
24 | {
25 | }
26 |
27 | ///
28 | /// Gets or sets the "error" value returned to the caller as part
29 | /// of the WWW-Authenticate header. This property may be null when
30 | /// is set to false.
31 | ///
32 | public string Error { get; set; }
33 |
34 | ///
35 | /// Gets or sets the "error_description" value returned to the caller as part
36 | /// of the WWW-Authenticate header. This property may be null when
37 | /// is set to false.
38 | ///
39 | public string ErrorDescription { get; set; }
40 |
41 | ///
42 | /// Gets or sets the "error_uri" value returned to the caller as part of the
43 | /// WWW-Authenticate header. This property is always null unless explicitly set.
44 | ///
45 | public string ErrorUri { get; set; }
46 |
47 | ///
48 | /// Gets or sets the "realm" value returned to
49 | /// the caller as part of the WWW-Authenticate header.
50 | ///
51 | public string Realm { get; set; }
52 |
53 | ///
54 | /// Gets or sets the "scope" value returned to
55 | /// the caller as part of the WWW-Authenticate header.
56 | ///
57 | public string Scope { get; set; }
58 |
59 | ///
60 | /// Gets a boolean indicating if the operation was handled from user code.
61 | ///
62 | public bool Handled { get; private set; }
63 |
64 | ///
65 | /// Marks the operation as handled to prevent the default logic from being applied.
66 | ///
67 | public void HandleResponse() => Handled = true;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/Events/CreateTicketContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System.Security.Claims;
8 | using JetBrains.Annotations;
9 | using Microsoft.AspNetCore.Authentication;
10 | using Microsoft.AspNetCore.Http;
11 |
12 | namespace AspNet.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Allows interception of the AuthenticationTicket creation process.
16 | ///
17 | public class CreateTicketContext : ResultContext
18 | {
19 | public CreateTicketContext(
20 | [NotNull] HttpContext context,
21 | [NotNull] AuthenticationScheme scheme,
22 | [NotNull] OAuthValidationOptions options,
23 | [NotNull] AuthenticationTicket ticket)
24 | : base(context, scheme, options)
25 | {
26 | Principal = ticket.Principal;
27 | Properties = ticket.Properties;
28 | }
29 |
30 | ///
31 | /// Gets the identity containing the user claims.
32 | ///
33 | public ClaimsIdentity Identity => Principal?.Identity as ClaimsIdentity;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/Events/DecryptTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Validation
12 | {
13 | ///
14 | /// Allows custom decryption of access tokens.
15 | ///
16 | public class DecryptTokenContext : ResultContext
17 | {
18 | public DecryptTokenContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] string token)
23 | : base(context, scheme, options)
24 | {
25 | Token = token;
26 | }
27 |
28 | ///
29 | /// Gets the access token.
30 | ///
31 | public string Token { get; }
32 |
33 | ///
34 | /// Gets or sets the data format used to deserialize the authentication ticket.
35 | ///
36 | public ISecureDataFormat DataFormat { get; set; }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/Events/RetrieveTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Validation
12 | {
13 | ///
14 | /// Allows custom parsing of access tokens from requests.
15 | ///
16 | public class RetrieveTokenContext : ResultContext
17 | {
18 | public RetrieveTokenContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthValidationOptions options)
22 | : base(context, scheme, options)
23 | {
24 | }
25 |
26 | ///
27 | /// Gets or sets the access token.
28 | ///
29 | public string Token { get; set; }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/Events/ValidateTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.AspNetCore.Authentication;
9 | using Microsoft.AspNetCore.Http;
10 |
11 | namespace AspNet.Security.OAuth.Validation
12 | {
13 | ///
14 | /// Allows customization of the token validation logic.
15 | ///
16 | public class ValidateTokenContext : ResultContext
17 | {
18 | public ValidateTokenContext(
19 | [NotNull] HttpContext context,
20 | [NotNull] AuthenticationScheme scheme,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] AuthenticationTicket ticket)
23 | : base(context, scheme, options)
24 | {
25 | Principal = ticket.Principal;
26 | Properties = ticket.Properties;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationConstants.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Validation
8 | {
9 | public static class OAuthValidationConstants
10 | {
11 | public static class Claims
12 | {
13 | public const string Scope = "scope";
14 | public const string Subject = "subject";
15 | }
16 |
17 | public static class Errors
18 | {
19 | public const string InsufficientScope = "insufficient_scope";
20 | public const string InvalidRequest = "invalid_request";
21 | public const string InvalidToken = "invalid_token";
22 | }
23 |
24 | public static class Parameters
25 | {
26 | public const string Error = "error";
27 | public const string ErrorDescription = "error_description";
28 | public const string ErrorUri = "error_uri";
29 | public const string Realm = "realm";
30 | public const string Scope = "scope";
31 | }
32 |
33 | public static class Properties
34 | {
35 | public const string Audiences = ".audiences";
36 | public const string Error = ".error";
37 | public const string ErrorDescription = ".error_description";
38 | public const string ErrorUri = ".error_uri";
39 | public const string Realm = ".realm";
40 | public const string Scope = ".scope";
41 | public const string Scopes = ".scopes";
42 | public const string Token = "access_token";
43 | }
44 |
45 | public static class Schemes
46 | {
47 | public const string Bearer = "Bearer";
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationDefaults.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Validation
8 | {
9 | public static class OAuthValidationDefaults
10 | {
11 | ///
12 | /// Gets the default scheme used by the validation middleware.
13 | ///
14 | public const string AuthenticationScheme = "Bearer";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationError.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Validation
8 | {
9 | ///
10 | /// Represents an OAuth2 validation error.
11 | ///
12 | public class OAuthValidationError
13 | {
14 | ///
15 | /// Gets or sets the error code.
16 | ///
17 | public string Error { get; set; }
18 |
19 | ///
20 | /// Gets or sets the error_description.
21 | ///
22 | public string ErrorDescription { get; set; }
23 |
24 | ///
25 | /// Gets or sets the error_uri.
26 | ///
27 | public string ErrorUri { get; set; }
28 |
29 | ///
30 | /// Gets or sets the realm.
31 | ///
32 | public string Realm { get; set; }
33 |
34 | ///
35 | /// Gets or sets the scope.
36 | ///
37 | public string Scope { get; set; }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationEvents.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Threading.Tasks;
9 |
10 | namespace AspNet.Security.OAuth.Validation
11 | {
12 | ///
13 | /// Allows customization of validation handling within the middleware.
14 | ///
15 | public class OAuthValidationEvents
16 | {
17 | ///
18 | /// Invoked when a challenge response is returned to the caller.
19 | ///
20 | public Func OnApplyChallenge { get; set; } = context => Task.CompletedTask;
21 |
22 | ///
23 | /// Invoked when a ticket is to be created from an introspection response.
24 | ///
25 | public Func OnCreateTicket { get; set; } = context => Task.CompletedTask;
26 |
27 | ///
28 | /// Invoked when a token is to be decrypted.
29 | ///
30 | public Func OnDecryptToken { get; set; } = context => Task.CompletedTask;
31 |
32 | ///
33 | /// Invoked when a token is to be parsed from a newly-received request.
34 | ///
35 | public Func OnRetrieveToken { get; set; } = context => Task.CompletedTask;
36 |
37 | ///
38 | /// Invoked when a token is to be validated, before final processing.
39 | ///
40 | public Func OnValidateToken { get; set; } = context => Task.CompletedTask;
41 |
42 | ///
43 | /// Invoked when a challenge response is returned to the caller.
44 | ///
45 | public virtual Task ApplyChallenge(ApplyChallengeContext context) => OnApplyChallenge(context);
46 |
47 | ///
48 | /// Invoked when a ticket is to be created from an introspection response.
49 | ///
50 | public virtual Task CreateTicket(CreateTicketContext context) => OnCreateTicket(context);
51 |
52 | ///
53 | /// Invoked when a token is to be decrypted.
54 | ///
55 | public virtual Task DecryptToken(DecryptTokenContext context) => OnDecryptToken(context);
56 |
57 | ///
58 | /// Invoked when a token is to be parsed from a newly-received request.
59 | ///
60 | public virtual Task RetrieveToken(RetrieveTokenContext context) => OnRetrieveToken(context);
61 |
62 | ///
63 | /// Invoked when a token is to be validated, before final processing.
64 | ///
65 | public virtual Task ValidateToken(ValidateTokenContext context) => OnValidateToken(context);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationExtensions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using AspNet.Security.OAuth.Validation;
10 | using JetBrains.Annotations;
11 | using Microsoft.AspNetCore.Authentication;
12 | using Microsoft.Extensions.DependencyInjection.Extensions;
13 | using Microsoft.Extensions.Options;
14 |
15 | namespace Microsoft.Extensions.DependencyInjection
16 | {
17 | ///
18 | /// Provides extension methods used to configure the OAuth2
19 | /// validation middleware in an ASP.NET Core pipeline.
20 | ///
21 | public static class OAuthValidationExtensions
22 | {
23 | ///
24 | /// Adds a new instance of the OAuth2 validation middleware in the ASP.NET Core pipeline.
25 | ///
26 | /// The authentication builder.
27 | /// The authentication builder.
28 | public static AuthenticationBuilder AddOAuthValidation([NotNull] this AuthenticationBuilder builder)
29 | {
30 | return builder.AddOAuthValidation(OAuthValidationDefaults.AuthenticationScheme);
31 | }
32 |
33 | ///
34 | /// Adds a new instance of the OAuth2 validation middleware in the ASP.NET Core pipeline.
35 | ///
36 | /// The authentication builder.
37 | /// The delegate used to configure the validation options.
38 | /// The authentication builder.
39 | public static AuthenticationBuilder AddOAuthValidation(
40 | [NotNull] this AuthenticationBuilder builder,
41 | [NotNull] Action configuration)
42 | {
43 | return builder.AddOAuthValidation(OAuthValidationDefaults.AuthenticationScheme, configuration);
44 | }
45 |
46 | ///
47 | /// Adds a new instance of the OAuth2 validation middleware in the ASP.NET Core pipeline.
48 | ///
49 | /// The authentication builder.
50 | /// The authentication scheme associated with this instance.
51 | /// The authentication builder.
52 | [EditorBrowsable(EditorBrowsableState.Advanced)]
53 | public static AuthenticationBuilder AddOAuthValidation(
54 | [NotNull] this AuthenticationBuilder builder, [NotNull] string scheme)
55 | {
56 | return builder.AddOAuthValidation(scheme, options => { });
57 | }
58 |
59 | ///
60 | /// Adds a new instance of the OAuth2 validation middleware in the ASP.NET Core pipeline.
61 | ///
62 | /// The authentication builder.
63 | /// The authentication scheme associated with this instance.
64 | /// The delegate used to configure the validation options.
65 | /// The authentication builder.
66 | [EditorBrowsable(EditorBrowsableState.Advanced)]
67 | public static AuthenticationBuilder AddOAuthValidation(
68 | [NotNull] this AuthenticationBuilder builder, [NotNull] string scheme,
69 | [NotNull] Action configuration)
70 | {
71 | if (builder == null)
72 | {
73 | throw new ArgumentNullException(nameof(builder));
74 | }
75 |
76 | if (configuration == null)
77 | {
78 | throw new ArgumentNullException(nameof(configuration));
79 | }
80 |
81 | if (string.IsNullOrEmpty(scheme))
82 | {
83 | throw new ArgumentException("The scheme cannot be null or empty.", nameof(scheme));
84 | }
85 |
86 | // Note: TryAddEnumerable() is used here to ensure the initializer is only registered once.
87 | builder.Services.TryAddEnumerable(
88 | ServiceDescriptor.Singleton,
89 | OAuthValidationInitializer>());
90 |
91 | return builder.AddScheme(scheme, configuration);
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationFeature.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace AspNet.Security.OAuth.Validation
8 | {
9 | ///
10 | /// Exposes the OAuth2 validation details
11 | /// associated with the current request.
12 | ///
13 | public class OAuthValidationFeature
14 | {
15 | ///
16 | /// Gets or sets the error details returned
17 | /// as part of the challenge response.
18 | ///
19 | public OAuthValidationError Error { get; set; }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationHelpers.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using JetBrains.Annotations;
9 | using Microsoft.AspNetCore.Authentication;
10 |
11 | namespace AspNet.Security.OAuth.Validation
12 | {
13 | ///
14 | /// Defines a set of commonly used helpers.
15 | ///
16 | internal static class OAuthValidationHelpers
17 | {
18 | ///
19 | /// Gets a given property from the authentication properties.
20 | ///
21 | /// The authentication properties.
22 | /// The specific property to look for.
23 | /// The value corresponding to the property, or null if the property cannot be found.
24 | public static string GetProperty([NotNull] this AuthenticationProperties properties, [NotNull] string property)
25 | {
26 | if (properties == null)
27 | {
28 | throw new ArgumentNullException(nameof(properties));
29 | }
30 |
31 | if (string.IsNullOrEmpty(property))
32 | {
33 | throw new ArgumentException("The property name cannot be null or empty.", nameof(property));
34 | }
35 |
36 | if (!properties.Items.TryGetValue(property, out string value))
37 | {
38 | return null;
39 | }
40 |
41 | return value;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationInitializer.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.ComponentModel;
9 | using JetBrains.Annotations;
10 | using Microsoft.AspNetCore.Authentication;
11 | using Microsoft.AspNetCore.DataProtection;
12 | using Microsoft.Extensions.Options;
13 |
14 | namespace AspNet.Security.OAuth.Validation
15 | {
16 | ///
17 | /// Contains the methods required to ensure that the configuration used by
18 | /// the OAuth2 validation handler is in a consistent and valid state.
19 | ///
20 | [EditorBrowsable(EditorBrowsableState.Never)]
21 | public class OAuthValidationInitializer : IPostConfigureOptions
22 | {
23 | private readonly IDataProtectionProvider _dataProtectionProvider;
24 |
25 | ///
26 | /// Creates a new instance of the class.
27 | ///
28 | public OAuthValidationInitializer([NotNull] IDataProtectionProvider dataProtectionProvider)
29 | {
30 | _dataProtectionProvider = dataProtectionProvider;
31 | }
32 |
33 | ///
34 | /// Populates the default OAuth2 validation options and ensure
35 | /// that the configuration is in a consistent and valid state.
36 | ///
37 | /// The authentication scheme associated with the handler instance.
38 | /// The options instance to initialize.
39 | public void PostConfigure([NotNull] string name, [NotNull] OAuthValidationOptions options)
40 | {
41 | if (options == null)
42 | {
43 | throw new ArgumentNullException(nameof(options));
44 | }
45 |
46 | if (string.IsNullOrEmpty(name))
47 | {
48 | throw new ArgumentException("The options instance name cannot be null or empty.", nameof(name));
49 | }
50 |
51 | if (options.Events == null)
52 | {
53 | options.Events = new OAuthValidationEvents();
54 | }
55 |
56 | if (options.DataProtectionProvider == null)
57 | {
58 | options.DataProtectionProvider = _dataProtectionProvider;
59 | }
60 |
61 | if (options.AccessTokenFormat == null)
62 | {
63 | // Note: the following purposes must match the ones used by the OpenID Connect server middleware.
64 | var protector = options.DataProtectionProvider.CreateProtector(
65 | "OpenIdConnectServerHandler", nameof(options.AccessTokenFormat), "ASOS");
66 |
67 | options.AccessTokenFormat = new TicketDataFormat(protector);
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/AspNet.Security.OAuth.Validation/OAuthValidationOptions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using Microsoft.AspNetCore.Authentication;
10 | using Microsoft.AspNetCore.DataProtection;
11 |
12 | namespace AspNet.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Exposes various settings needed to control
16 | /// the behavior of the validation middleware.
17 | ///
18 | public class OAuthValidationOptions : AuthenticationSchemeOptions
19 | {
20 | ///
21 | /// Creates a new instance of the class.
22 | ///
23 | public OAuthValidationOptions()
24 | {
25 | Events = new OAuthValidationEvents();
26 | }
27 |
28 | ///
29 | /// Gets the intended audiences of this resource server.
30 | /// Setting this property is recommended when the authorization
31 | /// server issues access tokens for multiple distinct resource servers.
32 | ///
33 | public ISet Audiences { get; } = new HashSet(StringComparer.Ordinal);
34 |
35 | ///
36 | /// Gets or sets the optional "realm" value returned to
37 | /// the caller as part of the WWW-Authenticate header.
38 | ///
39 | public string Realm { get; set; }
40 |
41 | ///
42 | /// Gets or sets a boolean determining whether the access token should be stored in the
43 | /// after a successful authentication process.
44 | ///
45 | public bool SaveToken { get; set; } = true;
46 |
47 | ///
48 | /// Gets or sets a boolean determining whether the token validation errors should be returned to the caller.
49 | /// Enabled by default, this option can be disabled to prevent the validation middleware from returning
50 | /// an error, an error_description and/or an error_uri in the WWW-Authenticate header.
51 | ///
52 | public bool IncludeErrorDetails { get; set; } = true;
53 |
54 | ///
55 | /// Gets or sets the object provided by the application to process events raised by the authentication middleware.
56 | /// The application may implement the interface fully, or it may create an instance of
57 | /// and assign delegates only to the events it wants to process.
58 | ///
59 | public new OAuthValidationEvents Events
60 | {
61 | get => (OAuthValidationEvents) base.Events;
62 | set => base.Events = value;
63 | }
64 |
65 | ///
66 | /// Gets or sets the clock used to determine the current date/time.
67 | ///
68 | public ISystemClock SystemClock { get; set; } = new SystemClock();
69 |
70 | ///
71 | /// Gets or sets the data format used to unprotect the
72 | /// access tokens received by the validation middleware.
73 | ///
74 | public ISecureDataFormat AccessTokenFormat { get; set; }
75 |
76 | ///
77 | /// Gets or sets the data protection provider used to create the default
78 | /// data protectors used by the OAuth2 validation handler.
79 | /// When this property is set to null, the data protection provider
80 | /// is directly retrieved from the dependency injection container.
81 | ///
82 | public IDataProtectionProvider DataProtectionProvider { get; set; }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/Events/ApplyChallengeContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Introspection
13 | {
14 | ///
15 | /// Allows customization of the challenge process.
16 | ///
17 | public class ApplyChallengeContext : BaseContext
18 | {
19 | public ApplyChallengeContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthIntrospectionOptions options,
22 | [NotNull] AuthenticationProperties properties)
23 | : base(context, options)
24 | {
25 | Properties = properties;
26 | }
27 |
28 | ///
29 | /// Gets the authentication properties associated with the challenge.
30 | ///
31 | public AuthenticationProperties Properties { get; }
32 |
33 | ///
34 | /// Gets or sets the "error" value returned to the caller as part
35 | /// of the WWW-Authenticate header. This property may be null when
36 | /// is set to false.
37 | ///
38 | public string Error { get; set; }
39 |
40 | ///
41 | /// Gets or sets the "error_description" value returned to the caller as part
42 | /// of the WWW-Authenticate header. This property may be null when
43 | /// is set to false.
44 | ///
45 | public string ErrorDescription { get; set; }
46 |
47 | ///
48 | /// Gets or sets the "error_uri" value returned to the caller as part of the
49 | /// WWW-Authenticate header. This property is always null unless explicitly set.
50 | ///
51 | public string ErrorUri { get; set; }
52 |
53 | ///
54 | /// Gets or sets the "realm" value returned to
55 | /// the caller as part of the WWW-Authenticate header.
56 | ///
57 | public string Realm { get; set; }
58 |
59 | ///
60 | /// Gets or sets the "scope" value returned to
61 | /// the caller as part of the WWW-Authenticate header.
62 | ///
63 | public string Scope { get; set; }
64 |
65 | ///
66 | /// Gets a boolean indicating if the operation was handled from user code.
67 | ///
68 | public bool Handled { get; private set; }
69 |
70 | ///
71 | /// Marks the operation as handled to prevent the default logic from being applied.
72 | ///
73 | public void HandleResponse() => Handled = true;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/Events/CreateTicketContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 | using Newtonsoft.Json.Linq;
12 |
13 | namespace Owin.Security.OAuth.Introspection
14 | {
15 | ///
16 | /// Allows interception of the AuthenticationTicket creation process.
17 | ///
18 | public class CreateTicketContext : BaseContext
19 | {
20 | public CreateTicketContext(
21 | [NotNull] IOwinContext context,
22 | [NotNull] OAuthIntrospectionOptions options,
23 | [NotNull] AuthenticationTicket ticket,
24 | [NotNull] JObject payload)
25 | : base(context, options)
26 | {
27 | Ticket = ticket;
28 | Payload = payload;
29 | }
30 |
31 | ///
32 | /// Gets the payload extracted from the introspection response.
33 | ///
34 | public JObject Payload { get; }
35 |
36 | ///
37 | /// Gets or sets the created by the application.
38 | ///
39 | public AuthenticationTicket Ticket { get; set; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/Events/RetrieveTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Introspection
13 | {
14 | ///
15 | /// Allows custom parsing of access tokens from requests.
16 | ///
17 | public class RetrieveTokenContext : BaseContext
18 | {
19 | public RetrieveTokenContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthIntrospectionOptions options)
22 | : base(context, options)
23 | {
24 | }
25 |
26 | ///
27 | /// Gets or sets the access token.
28 | ///
29 | public string Token { get; set; }
30 |
31 | ///
32 | /// Gets or sets the created by the application.
33 | ///
34 | public AuthenticationTicket Ticket { get; set; }
35 |
36 | ///
37 | /// Gets a boolean indicating if the operation was handled from user code.
38 | ///
39 | public bool Handled { get; private set; }
40 |
41 | ///
42 | /// Marks the operation as handled to prevent the default logic from being applied.
43 | ///
44 | public void HandleValidation() => Handled = true;
45 |
46 | ///
47 | /// Marks the operation as handled to prevent the default logic from being applied.
48 | ///
49 | /// The authentication ticket to use.
50 | public void HandleValidation(AuthenticationTicket ticket)
51 | {
52 | Ticket = ticket;
53 | Handled = true;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/Events/SendIntrospectionRequestContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System.Net.Http;
8 | using JetBrains.Annotations;
9 | using Microsoft.Owin;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Introspection
13 | {
14 | ///
15 | /// Allows for custom handling of the call to the Authorization Server's Introspection endpoint.
16 | ///
17 | public class SendIntrospectionRequestContext : BaseContext
18 | {
19 | public SendIntrospectionRequestContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthIntrospectionOptions options,
22 | [NotNull] HttpRequestMessage request,
23 | [NotNull] string token)
24 | : base(context, options)
25 | {
26 | Request = request;
27 | Token = token;
28 | }
29 |
30 | ///
31 | /// An for use by the application to call the authorization server.
32 | ///
33 | public HttpClient Client => Options.HttpClient;
34 |
35 | ///
36 | /// Gets the HTTP request sent to the introspection endpoint.
37 | ///
38 | public new HttpRequestMessage Request { get; }
39 |
40 | ///
41 | /// Gets or sets the HTTP response returned by the introspection endpoint.
42 | ///
43 | public new HttpResponseMessage Response { get; set; }
44 |
45 | ///
46 | /// The access token parsed from the client request.
47 | ///
48 | public string Token { get; }
49 |
50 | ///
51 | /// Gets a boolean indicating if the operation was handled from user code.
52 | ///
53 | public bool Handled { get; private set; }
54 |
55 | ///
56 | /// Marks the operation as handled to prevent the default logic from being applied.
57 | ///
58 | public void HandleResponse() => Handled = true;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/Events/ValidateTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Introspection
13 | {
14 | ///
15 | /// Allows customization of the token validation logic.
16 | ///
17 | public class ValidateTokenContext : BaseContext
18 | {
19 | public ValidateTokenContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthIntrospectionOptions options,
22 | [NotNull] AuthenticationTicket ticket)
23 | : base(context, options)
24 | {
25 | Ticket = ticket;
26 | }
27 |
28 | ///
29 | /// Gets or sets the
30 | /// created from the introspection response.
31 | ///
32 | public AuthenticationTicket Ticket { get; set; }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionConfiguration.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Threading;
10 | using System.Threading.Tasks;
11 | using JetBrains.Annotations;
12 | using Microsoft.IdentityModel.Protocols;
13 | using Microsoft.IdentityModel.Protocols.OpenIdConnect;
14 | using Newtonsoft.Json;
15 |
16 | namespace Owin.Security.OAuth.Introspection
17 | {
18 | ///
19 | /// Represents an OAuth2 introspection configuration.
20 | ///
21 | [JsonObject(MemberSerialization = MemberSerialization.OptIn)]
22 | public class OAuthIntrospectionConfiguration : OpenIdConnectConfiguration
23 | {
24 | ///
25 | /// Initializes a new instance of the class.
26 | ///
27 | public OAuthIntrospectionConfiguration()
28 | : base() { }
29 |
30 | ///
31 | /// Initializes a new instance of the class.
32 | ///
33 | /// The JSON payload used to initialize the current instance.
34 | public OAuthIntrospectionConfiguration([NotNull] string json)
35 | : base(json) { }
36 |
37 | ///
38 | /// Gets or sets the introspection endpoint address.
39 | ///
40 | [JsonProperty(
41 | DefaultValueHandling = DefaultValueHandling.Ignore,
42 | NullValueHandling = NullValueHandling.Ignore,
43 | PropertyName = OAuthIntrospectionConstants.Metadata.IntrospectionEndpoint)]
44 | public string IntrospectionEndpoint { get; set; }
45 |
46 | ///
47 | /// Gets the list of authentication methods supported by the introspection endpoint.
48 | ///
49 | [JsonProperty(
50 | DefaultValueHandling = DefaultValueHandling.Ignore,
51 | NullValueHandling = NullValueHandling.Ignore,
52 | PropertyName = OAuthIntrospectionConstants.Metadata.IntrospectionEndpointAuthMethodsSupported)]
53 | public ISet IntrospectionEndpointAuthMethodsSupported { get; } = new HashSet();
54 |
55 | ///
56 | /// Represents a configuration retriever able to deserialize
57 | /// instances.
58 | ///
59 | public class Retriever : IConfigurationRetriever
60 | {
61 | ///
62 | /// Retrieves the OAuth2 introspection configuration from the specified address.
63 | ///
64 | /// The address of the discovery document.
65 | /// The object used to retrieve the discovery document.
66 | /// The that can be used to abort the operation.
67 | /// An instance.
68 | public async Task GetConfigurationAsync(
69 | [NotNull] string address, [NotNull] IDocumentRetriever retriever, CancellationToken cancellationToken)
70 | {
71 | if (string.IsNullOrEmpty(address))
72 | {
73 | throw new ArgumentException("The address cannot be null or empty.", nameof(address));
74 | }
75 |
76 | if (retriever == null)
77 | {
78 | throw new ArgumentNullException(nameof(retriever));
79 | }
80 |
81 | return new OAuthIntrospectionConfiguration(await retriever.GetDocumentAsync(address, cancellationToken));
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionConstants.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace Owin.Security.OAuth.Introspection
8 | {
9 | public static class OAuthIntrospectionConstants
10 | {
11 | public static class Claims
12 | {
13 | public const string Active = "active";
14 | public const string Audience = "aud";
15 | public const string ExpiresAt = "exp";
16 | public const string IssuedAt = "iat";
17 | public const string JwtId = "jti";
18 | public const string Name = "name";
19 | public const string NotBefore = "nbf";
20 | public const string Role = "role";
21 | public const string Scope = "scope";
22 | public const string Subject = "sub";
23 | public const string TokenType = "token_type";
24 | public const string TokenUsage = "token_usage";
25 | public const string Username = "username";
26 | }
27 |
28 | public static class ClaimValueTypes
29 | {
30 | public const string Json = "JSON";
31 | public const string JsonArray = "JSON_ARRAY";
32 | }
33 |
34 | public static class ClientAuthenticationMethods
35 | {
36 | public const string ClientSecretBasic = "client_secret_basic";
37 | public const string ClientSecretPost = "client_secret_post";
38 | }
39 |
40 | public static class Errors
41 | {
42 | public const string InsufficientScope = "insufficient_scope";
43 | public const string InvalidRequest = "invalid_request";
44 | public const string InvalidToken = "invalid_token";
45 | }
46 |
47 | public static class Headers
48 | {
49 | public const string Authorization = "Authorization";
50 | public const string WWWAuthenticate = "WWW-Authenticate";
51 | }
52 |
53 | public static class Metadata
54 | {
55 | public const string IntrospectionEndpoint = "introspection_endpoint";
56 | public const string IntrospectionEndpointAuthMethodsSupported = "introspection_endpoint_auth_methods_supported";
57 | }
58 |
59 | public static class Parameters
60 | {
61 | public const string ClientId = "client_id";
62 | public const string ClientSecret = "client_secret";
63 | public const string Error = "error";
64 | public const string ErrorDescription = "error_description";
65 | public const string ErrorUri = "error_uri";
66 | public const string Realm = "realm";
67 | public const string Scope = "scope";
68 | public const string Token = "token";
69 | public const string TokenTypeHint = "token_type_hint";
70 | }
71 |
72 | public static class Properties
73 | {
74 | public const string AccessToken = "access_token";
75 | public const string Audiences = ".audiences";
76 | public const string Error = ".error";
77 | public const string ErrorDescription = ".error_description";
78 | public const string ErrorUri = ".error_uri";
79 | public const string Realm = ".realm";
80 | public const string Scope = ".scope";
81 | public const string Scopes = ".scopes";
82 | public const string TokenId = ".token_id";
83 | public const string TokenUsage = ".token_usage";
84 | }
85 |
86 | public static class Schemes
87 | {
88 | public const string Basic = "Basic";
89 | public const string Bearer = "Bearer";
90 | }
91 |
92 | public static class Separators
93 | {
94 | public static readonly char[] Space = { ' ' };
95 | }
96 |
97 | public static class TokenTypeHints
98 | {
99 | public const string AccessToken = "access_token";
100 | }
101 |
102 | public static class TokenUsages
103 | {
104 | public const string AccessToken = "access_token";
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionDefaults.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace Owin.Security.OAuth.Introspection
8 | {
9 | public static class OAuthIntrospectionDefaults
10 | {
11 | ///
12 | /// Gets the default scheme used by the introspection middleware.
13 | ///
14 | public const string AuthenticationScheme = "Bearer";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionError.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace Owin.Security.OAuth.Introspection
8 | {
9 | ///
10 | /// Represents an OAuth2 introspection error.
11 | ///
12 | public class OAuthIntrospectionError
13 | {
14 | ///
15 | /// Gets or sets the error code.
16 | ///
17 | public string Error { get; set; }
18 |
19 | ///
20 | /// Gets or sets the error_description.
21 | ///
22 | public string ErrorDescription { get; set; }
23 |
24 | ///
25 | /// Gets or sets the error_uri.
26 | ///
27 | public string ErrorUri { get; set; }
28 |
29 | ///
30 | /// Gets or sets the realm.
31 | ///
32 | public string Realm { get; set; }
33 |
34 | ///
35 | /// Gets or sets the scope.
36 | ///
37 | public string Scope { get; set; }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionEvents.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Threading.Tasks;
9 |
10 | namespace Owin.Security.OAuth.Introspection
11 | {
12 | ///
13 | /// Allows customization of introspection handling within the middleware.
14 | ///
15 | public class OAuthIntrospectionEvents
16 | {
17 | ///
18 | /// Invoked when a challenge response is returned to the caller.
19 | ///
20 | public Func OnApplyChallenge { get; set; } = context => Task.CompletedTask;
21 |
22 | ///
23 | /// Invoked when a ticket is to be created from an introspection response.
24 | ///
25 | public Func OnCreateTicket { get; set; } = context => Task.CompletedTask;
26 |
27 | ///
28 | /// Invoked when a token is to be parsed from a newly-received request.
29 | ///
30 | public Func OnRetrieveToken { get; set; } = context => Task.CompletedTask;
31 |
32 | ///
33 | /// Invoked when a token is to be sent to the authorization server for introspection.
34 | ///
35 | public Func OnSendIntrospectionRequest { get; set; } = context => Task.CompletedTask;
36 |
37 | ///
38 | /// Invoked when a token is to be validated, before final processing.
39 | ///
40 | public Func OnValidateToken { get; set; } = context => Task.CompletedTask;
41 |
42 | ///
43 | /// Invoked when a challenge response is returned to the caller.
44 | ///
45 | public virtual Task ApplyChallenge(ApplyChallengeContext context) => OnApplyChallenge(context);
46 |
47 | ///
48 | /// Invoked when a ticket is to be created from an introspection response.
49 | ///
50 | public virtual Task CreateTicket(CreateTicketContext context) => OnCreateTicket(context);
51 |
52 | ///
53 | /// Invoked when a token is to be parsed from a newly-received request.
54 | ///
55 | public virtual Task RetrieveToken(RetrieveTokenContext context) => OnRetrieveToken(context);
56 |
57 | ///
58 | /// Invoked when a token is to be sent to the authorization server for introspection.
59 | ///
60 | public virtual Task SendIntrospectionRequest(SendIntrospectionRequestContext context) => OnSendIntrospectionRequest(context);
61 |
62 | ///
63 | /// Invoked when a token is to be validated, before final processing.
64 | ///
65 | public virtual Task ValidateToken(ValidateTokenContext context) => OnValidateToken(context);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionExtensions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using JetBrains.Annotations;
9 | using Microsoft.Extensions.Logging;
10 | using Owin.Security.OAuth.Introspection;
11 |
12 | namespace Owin
13 | {
14 | ///
15 | /// Provides extension methods used to configure the OAuth2
16 | /// introspection middleware in an OWIN/Katana pipeline.
17 | ///
18 | public static class OAuthIntrospectionExtensions
19 | {
20 | ///
21 | /// Adds a new instance of the OAuth2 introspection middleware in the OWIN/Katana pipeline.
22 | ///
23 | /// The application builder.
24 | /// The delegate used to configure the introspection options.
25 | /// The application builder.
26 | public static IAppBuilder UseOAuthIntrospection(
27 | [NotNull] this IAppBuilder app,
28 | [NotNull] Action configuration)
29 | {
30 | if (app == null)
31 | {
32 | throw new ArgumentNullException(nameof(app));
33 | }
34 |
35 | if (configuration == null)
36 | {
37 | throw new ArgumentNullException(nameof(configuration));
38 | }
39 |
40 | var options = new OAuthIntrospectionOptions();
41 | configuration(options);
42 |
43 | return app.UseOAuthIntrospection(options);
44 | }
45 |
46 | ///
47 | /// Adds a new instance of the OAuth2 introspection middleware in the OWIN/Katana pipeline.
48 | ///
49 | /// The application builder.
50 | /// The options used to configure the introspection middleware.
51 | /// The application builder.
52 | public static IAppBuilder UseOAuthIntrospection(
53 | [NotNull] this IAppBuilder app,
54 | [NotNull] OAuthIntrospectionOptions options)
55 | {
56 | if (app == null)
57 | {
58 | throw new ArgumentNullException(nameof(app));
59 | }
60 |
61 | if (options == null)
62 | {
63 | throw new ArgumentNullException(nameof(options));
64 | }
65 |
66 | return app.Use(app.Properties, options);
67 | }
68 |
69 | ///
70 | /// Configures the OAuth2 introspection middleware to enable logging.
71 | ///
72 | /// The options used to configure the OAuth2 introspection middleware.
73 | /// The delegate used to configure the logger factory.
74 | /// The options used to configure the OAuth2 introspection middleware.
75 | public static OAuthIntrospectionOptions UseLogging(
76 | [NotNull] this OAuthIntrospectionOptions options,
77 | [NotNull] Action configuration)
78 | {
79 | if (options == null)
80 | {
81 | throw new ArgumentNullException(nameof(options));
82 | }
83 |
84 | if (configuration == null)
85 | {
86 | throw new ArgumentNullException(nameof(configuration));
87 | }
88 |
89 | var factory = new LoggerFactory();
90 | configuration(factory);
91 |
92 | options.Logger = factory.CreateLogger();
93 |
94 | return options;
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionHelpers.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using JetBrains.Annotations;
9 | using Microsoft.Owin.Security;
10 |
11 | namespace Owin.Security.OAuth.Introspection
12 | {
13 | ///
14 | /// Defines a set of commonly used helpers.
15 | ///
16 | internal static class OAuthIntrospectionHelpers
17 | {
18 | ///
19 | /// Gets a given property from the authentication properties.
20 | ///
21 | /// The authentication properties.
22 | /// The specific property to look for.
23 | /// The value corresponding to the property, or null if the property cannot be found.
24 | public static string GetProperty([NotNull] this AuthenticationProperties properties, [NotNull] string property)
25 | {
26 | if (properties == null)
27 | {
28 | throw new ArgumentNullException(nameof(properties));
29 | }
30 |
31 | if (string.IsNullOrEmpty(property))
32 | {
33 | throw new ArgumentException("The property name cannot be null or empty.", nameof(property));
34 | }
35 |
36 | if (!properties.Dictionary.TryGetValue(property, out string value))
37 | {
38 | return null;
39 | }
40 |
41 | return value;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionMiddleware.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Net.Http;
10 | using JetBrains.Annotations;
11 | using Microsoft.AspNetCore.DataProtection;
12 | using Microsoft.Extensions.Caching.Distributed;
13 | using Microsoft.Extensions.Caching.Memory;
14 | using Microsoft.Extensions.Logging.Abstractions;
15 | using Microsoft.Extensions.Options;
16 | using Microsoft.IdentityModel.Protocols;
17 | using Microsoft.Owin;
18 | using Microsoft.Owin.BuilderProperties;
19 | using Microsoft.Owin.Security.Infrastructure;
20 | using Microsoft.Owin.Security.Interop;
21 |
22 | namespace Owin.Security.OAuth.Introspection
23 | {
24 | ///
25 | /// Provides the entry point necessary to register the
26 | /// OAuth2 introspection handler in an OWIN/Katana pipeline.
27 | ///
28 | public class OAuthIntrospectionMiddleware : AuthenticationMiddleware
29 | {
30 | ///
31 | /// Creates a new instance of the class.
32 | ///
33 | public OAuthIntrospectionMiddleware(
34 | [NotNull] OwinMiddleware next,
35 | [NotNull] IDictionary properties,
36 | [NotNull] OAuthIntrospectionOptions options)
37 | : base(next, options)
38 | {
39 | if (string.IsNullOrEmpty(options.ClientId) || string.IsNullOrEmpty(options.ClientSecret))
40 | {
41 | throw new ArgumentException("Client credentials must be configured.", nameof(options));
42 | }
43 |
44 | if (Options.Events == null)
45 | {
46 | Options.Events = new OAuthIntrospectionEvents();
47 | }
48 |
49 | if (options.DataProtectionProvider == null)
50 | {
51 | // Use the application name provided by the OWIN host as the Data Protection discriminator.
52 | // If the application name cannot be resolved, throw an invalid operation exception.
53 | var discriminator = new AppProperties(properties).AppName;
54 | if (string.IsNullOrEmpty(discriminator))
55 | {
56 | throw new InvalidOperationException("The application name cannot be resolved from the OWIN application builder. " +
57 | "Consider manually setting the 'DataProtectionProvider' property in the " +
58 | "options using 'DataProtectionProvider.Create([unique application name])'.");
59 | }
60 |
61 | options.DataProtectionProvider = DataProtectionProvider.Create(discriminator);
62 | }
63 |
64 | if (options.AccessTokenFormat == null)
65 | {
66 | var protector = Options.DataProtectionProvider.CreateProtector(
67 | nameof(OAuthIntrospectionHandler),
68 | nameof(Options.AccessTokenFormat), Options.AuthenticationType);
69 |
70 | options.AccessTokenFormat = new AspNetTicketDataFormat(new DataProtectorShim(protector));
71 | }
72 |
73 | if (options.Cache == null)
74 | {
75 | options.Cache = new MemoryDistributedCache(new OptionsWrapper(new MemoryDistributedCacheOptions()));
76 | }
77 |
78 | if (options.Logger == null)
79 | {
80 | options.Logger = NullLogger.Instance;
81 | }
82 |
83 | if (options.HttpClient == null)
84 | {
85 | options.HttpClient = new HttpClient
86 | {
87 | Timeout = TimeSpan.FromSeconds(15),
88 | MaxResponseContentBufferSize = 1024 * 1024 * 10
89 | };
90 |
91 | options.HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd("OWIN OAuth2 introspection middleware");
92 | }
93 |
94 | if (Options.ConfigurationManager == null)
95 | {
96 | if (Options.Configuration != null)
97 | {
98 | if (string.IsNullOrEmpty(Options.Configuration.IntrospectionEndpoint))
99 | {
100 | throw new ArgumentException("The introspection endpoint address cannot be null or empty.", nameof(options));
101 | }
102 |
103 | Options.ConfigurationManager = new StaticConfigurationManager(Options.Configuration);
104 | }
105 |
106 | else
107 | {
108 | if (Options.Authority == null && Options.MetadataAddress == null)
109 | {
110 | throw new ArgumentException("The authority or an absolute metadata endpoint address must be provided.", nameof(options));
111 | }
112 |
113 | if (Options.MetadataAddress == null)
114 | {
115 | Options.MetadataAddress = new Uri(".well-known/openid-configuration", UriKind.Relative);
116 | }
117 |
118 | if (!Options.MetadataAddress.IsAbsoluteUri)
119 | {
120 | if (Options.Authority == null || !Options.Authority.IsAbsoluteUri)
121 | {
122 | throw new ArgumentException("The authority must be provided and must be an absolute URL.", nameof(options));
123 | }
124 |
125 | if (!string.IsNullOrEmpty(Options.Authority.Fragment) || !string.IsNullOrEmpty(Options.Authority.Query))
126 | {
127 | throw new ArgumentException("The authority cannot contain a fragment or a query string.", nameof(options));
128 | }
129 |
130 | if (!Options.Authority.OriginalString.EndsWith("/"))
131 | {
132 | Options.Authority = new Uri(Options.Authority.OriginalString + "/", UriKind.Absolute);
133 | }
134 |
135 | Options.MetadataAddress = new Uri(Options.Authority, Options.MetadataAddress);
136 | }
137 |
138 | if (Options.RequireHttpsMetadata && !Options.MetadataAddress.Scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
139 | {
140 | throw new ArgumentException("The metadata endpoint address must be a HTTPS URL when " +
141 | "'RequireHttpsMetadata' is not set to 'false'.", nameof(options));
142 | }
143 |
144 | options.ConfigurationManager = new ConfigurationManager(
145 | options.MetadataAddress.AbsoluteUri, new OAuthIntrospectionConfiguration.Retriever(),
146 | new HttpDocumentRetriever(options.HttpClient) { RequireHttps = options.RequireHttpsMetadata });
147 | }
148 | }
149 | }
150 |
151 | ///
152 | /// Returns a new instance.
153 | ///
154 | /// A new instance of the class.
155 | protected override AuthenticationHandler CreateHandler()
156 | {
157 | return new OAuthIntrospectionHandler();
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/OAuthIntrospectionOptions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Net.Http;
10 | using Microsoft.AspNetCore.DataProtection;
11 | using Microsoft.Extensions.Caching.Distributed;
12 | using Microsoft.Extensions.Logging;
13 | using Microsoft.IdentityModel.Protocols;
14 | using Microsoft.Owin.Infrastructure;
15 | using Microsoft.Owin.Security;
16 |
17 | namespace Owin.Security.OAuth.Introspection
18 | {
19 | ///
20 | /// Exposes various settings needed to control
21 | /// the behavior of the introspection middleware.
22 | ///
23 | public class OAuthIntrospectionOptions : AuthenticationOptions
24 | {
25 | ///
26 | /// Creates a new instance of the class.
27 | ///
28 | public OAuthIntrospectionOptions()
29 | : base(OAuthIntrospectionDefaults.AuthenticationScheme)
30 | {
31 | AuthenticationMode = AuthenticationMode.Active;
32 | }
33 |
34 | ///
35 | /// Gets or sets the absolute URL of the OAuth2/OpenID Connect server.
36 | /// Note: this property is ignored when
37 | /// or are set.
38 | ///
39 | public Uri Authority { get; set; }
40 |
41 | ///
42 | /// Gets the intended audiences of this resource server.
43 | /// Setting this property is recommended when the authorization
44 | /// server issues access tokens for multiple distinct resource servers.
45 | ///
46 | public ISet Audiences { get; } = new HashSet(StringComparer.Ordinal);
47 |
48 | ///
49 | /// Gets or sets the URL of the OAuth2/OpenID Connect server discovery endpoint.
50 | /// When the URL is relative, must be set and absolute.
51 | /// Note: this property is ignored when
52 | /// or are set.
53 | ///
54 | public Uri MetadataAddress { get; set; }
55 |
56 | ///
57 | /// Gets or sets a boolean indicating whether HTTPS is required to retrieve the metadata document.
58 | /// The default value is true. This option should be used only in development environments.
59 | /// Note: this property is ignored when or are set.
60 | ///
61 | public bool RequireHttpsMetadata { get; set; } = true;
62 |
63 | ///
64 | /// Gets or sets the configuration used by the introspection middleware.
65 | /// Note: this property is ignored when is set.
66 | ///
67 | public OAuthIntrospectionConfiguration Configuration { get; set; }
68 |
69 | ///
70 | /// Gets or sets the configuration manager used by the introspection middleware.
71 | ///
72 | public IConfigurationManager ConfigurationManager { get; set; }
73 |
74 | ///
75 | /// Gets or sets the client identifier representing the resource server.
76 | ///
77 | public string ClientId { get; set; }
78 |
79 | ///
80 | /// Gets or sets the client secret used to
81 | /// communicate with the introspection endpoint.
82 | ///
83 | public string ClientSecret { get; set; }
84 |
85 | ///
86 | /// Gets or sets the optional "realm" value returned to
87 | /// the caller as part of the WWW-Authenticate header.
88 | ///
89 | public string Realm { get; set; }
90 |
91 | ///
92 | /// Gets or sets a boolean determining whether the access token should be stored in the
93 | /// after a successful authentication process.
94 | ///
95 | public bool SaveToken { get; set; } = true;
96 |
97 | ///
98 | /// Gets or sets a boolean determining whether the token validation errors should be returned to the caller.
99 | /// Enabled by default, this option can be disabled to prevent the introspection middleware from returning
100 | /// an error, an error_description and/or an error_uri in the WWW-Authenticate header.
101 | ///
102 | public bool IncludeErrorDetails { get; set; } = true;
103 |
104 | ///
105 | /// Gets or sets the claim type used for the name claim.
106 | /// By default, the standard
107 | /// claim defined by the OAuth2 introspection specification is used.
108 | ///
109 | public string NameClaimType { get; set; } = OAuthIntrospectionConstants.Claims.Name;
110 |
111 | ///
112 | /// Gets or sets the claim type used for the role claim(s).
113 | /// By default, is used.
114 | ///
115 | public string RoleClaimType { get; set; } = OAuthIntrospectionConstants.Claims.Role;
116 |
117 | ///
118 | /// Gets or sets the cache used to store the access tokens/authentication tickets
119 | /// and the introspection responses returned received by the resource server.
120 | ///
121 | public IDistributedCache Cache { get; set; }
122 |
123 | ///
124 | /// Gets or sets the caching policy used to determine
125 | /// how long the introspection responses should be cached.
126 | /// Note: this property can be set to null to
127 | /// prevent the introspection responses from being cached.
128 | ///
129 | public DistributedCacheEntryOptions CachingPolicy { get; set; } = new DistributedCacheEntryOptions
130 | {
131 | AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(15)
132 | };
133 |
134 | ///
135 | /// Gets or sets the object provided by the application to process events raised by the authentication middleware.
136 | /// The application may implement the interface fully, or it may create an instance of
137 | /// and assign delegates only to the events it wants to process.
138 | ///
139 | public OAuthIntrospectionEvents Events { get; set; } = new OAuthIntrospectionEvents();
140 |
141 | ///
142 | /// Gets or sets the HTTP client used to communicate with the remote OAuth2 server.
143 | ///
144 | public HttpClient HttpClient { get; set; }
145 |
146 | ///
147 | /// Gets or sets the logger used by the OAuth2 introspection handler.
148 | /// When unassigned, a default instance is created using the logger factory.
149 | ///
150 | public ILogger Logger { get; set; }
151 |
152 | ///
153 | /// Gets or sets the clock used to determine the current date/time.
154 | ///
155 | public ISystemClock SystemClock { get; set; } = new SystemClock();
156 |
157 | ///
158 | /// Gets or sets the data format used to serialize and deserialize
159 | /// the authenticated tickets stored in the distributed cache.
160 | ///
161 | public ISecureDataFormat AccessTokenFormat { get; set; }
162 |
163 | ///
164 | /// Gets or sets the data protection provider used to create the default
165 | /// data protectors used by the OAuth2 introspection handler.
166 | ///
167 | public IDataProtectionProvider DataProtectionProvider { get; set; }
168 | }
169 | }
170 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Introspection/Owin.Security.OAuth.Introspection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net461
7 |
8 |
9 |
10 | OAuth2 introspection middleware for OWIN/Katana.
11 | Kévin Chalet
12 | authentication;katana;jwt;openidconnect;owin;security
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/Events/ApplyChallengeContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Allows customization of the challenge process.
16 | ///
17 | public class ApplyChallengeContext : BaseContext
18 | {
19 | public ApplyChallengeContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] AuthenticationProperties properties)
23 | : base(context, options)
24 | {
25 | Properties = properties;
26 | }
27 |
28 | ///
29 | /// Gets the authentication properties associated with the challenge.
30 | ///
31 | public AuthenticationProperties Properties { get; }
32 |
33 | ///
34 | /// Gets or sets the "error" value returned to the caller as part
35 | /// of the WWW-Authenticate header. This property may be null when
36 | /// is set to false.
37 | ///
38 | public string Error { get; set; }
39 |
40 | ///
41 | /// Gets or sets the "error_description" value returned to the caller as part
42 | /// of the WWW-Authenticate header. This property may be null when
43 | /// is set to false.
44 | ///
45 | public string ErrorDescription { get; set; }
46 |
47 | ///
48 | /// Gets or sets the "error_uri" value returned to the caller as part of the
49 | /// WWW-Authenticate header. This property is always null unless explicitly set.
50 | ///
51 | public string ErrorUri { get; set; }
52 |
53 | ///
54 | /// Gets or sets the "realm" value returned to
55 | /// the caller as part of the WWW-Authenticate header.
56 | ///
57 | public string Realm { get; set; }
58 |
59 | ///
60 | /// Gets or sets the "scope" value returned to
61 | /// the caller as part of the WWW-Authenticate header.
62 | ///
63 | public string Scope { get; set; }
64 |
65 | ///
66 | /// Gets a boolean indicating if the operation was handled from user code.
67 | ///
68 | public bool Handled { get; private set; }
69 |
70 | ///
71 | /// Marks the operation as handled to prevent the default logic from being applied.
72 | ///
73 | public void HandleResponse() => Handled = true;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/Events/CreateTicketContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Allows interception of the AuthenticationTicket creation process.
16 | ///
17 | public class CreateTicketContext : BaseContext
18 | {
19 | public CreateTicketContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] AuthenticationTicket ticket)
23 | : base(context, options)
24 | {
25 | Ticket = ticket;
26 | }
27 |
28 | ///
29 | /// Gets or sets the created by the application.
30 | ///
31 | public AuthenticationTicket Ticket { get; set; }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/Events/DecryptTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Allows custom decryption of access tokens.
16 | ///
17 | public class DecryptTokenContext : BaseContext
18 | {
19 | public DecryptTokenContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] string token)
23 | : base(context, options)
24 | {
25 | Token = token;
26 | }
27 |
28 | ///
29 | /// Gets the access token.
30 | ///
31 | public string Token { get; }
32 |
33 | ///
34 | /// Gets or sets the data format used to deserialize the authentication ticket.
35 | ///
36 | public ISecureDataFormat DataFormat { get; set; }
37 |
38 | ///
39 | /// Gets or sets the
40 | /// extracted from the access token.
41 | ///
42 | public AuthenticationTicket Ticket { get; set; }
43 |
44 | ///
45 | /// Gets a boolean indicating if the operation was handled from user code.
46 | ///
47 | public bool Handled { get; private set; }
48 |
49 | ///
50 | /// Marks the operation as handled to prevent the default logic from being applied.
51 | ///
52 | public void HandleDecryption() => Handled = true;
53 |
54 | ///
55 | /// Marks the operation as handled to prevent the default logic from being applied.
56 | ///
57 | /// The authentication ticket to use.
58 | public void HandleDecryption(AuthenticationTicket ticket)
59 | {
60 | Ticket = ticket;
61 | Handled = true;
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/Events/RetrieveTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Allows custom parsing of access tokens from requests.
16 | ///
17 | public class RetrieveTokenContext : BaseContext
18 | {
19 | public RetrieveTokenContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthValidationOptions options)
22 | : base(context, options)
23 | {
24 | }
25 |
26 | ///
27 | /// Gets or sets the access token.
28 | ///
29 | public string Token { get; set; }
30 |
31 | ///
32 | /// Gets or sets the created by the application.
33 | ///
34 | public AuthenticationTicket Ticket { get; set; }
35 |
36 | ///
37 | /// Gets a boolean indicating if the operation was handled from user code.
38 | ///
39 | public bool Handled { get; private set; }
40 |
41 | ///
42 | /// Marks the operation as handled to prevent the default logic from being applied.
43 | ///
44 | public void HandleValidation() => Handled = true;
45 |
46 | ///
47 | /// Marks the operation as handled to prevent the default logic from being applied.
48 | ///
49 | /// The authentication ticket to use.
50 | public void HandleValidation(AuthenticationTicket ticket)
51 | {
52 | Ticket = ticket;
53 | Handled = true;
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/Events/ValidateTokenContext.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using JetBrains.Annotations;
8 | using Microsoft.Owin;
9 | using Microsoft.Owin.Security;
10 | using Microsoft.Owin.Security.Provider;
11 |
12 | namespace Owin.Security.OAuth.Validation
13 | {
14 | ///
15 | /// Allows customization of the token validation logic.
16 | ///
17 | public class ValidateTokenContext : BaseContext
18 | {
19 | public ValidateTokenContext(
20 | [NotNull] IOwinContext context,
21 | [NotNull] OAuthValidationOptions options,
22 | [NotNull] AuthenticationTicket ticket)
23 | : base(context, options)
24 | {
25 | Ticket = ticket;
26 | }
27 |
28 | ///
29 | /// Gets or sets the
30 | /// extracted from the access token.
31 | ///
32 | public AuthenticationTicket Ticket { get; set; }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationConstants.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace Owin.Security.OAuth.Validation
8 | {
9 | public static class OAuthValidationConstants
10 | {
11 | public static class Claims
12 | {
13 | public const string Scope = "scope";
14 | public const string Subject = "subject";
15 | }
16 |
17 | public static class Errors
18 | {
19 | public const string InsufficientScope = "insufficient_scope";
20 | public const string InvalidRequest = "invalid_request";
21 | public const string InvalidToken = "invalid_token";
22 | }
23 |
24 | public static class Headers
25 | {
26 | public const string Authorization = "Authorization";
27 | public const string WWWAuthenticate = "WWW-Authenticate";
28 | }
29 |
30 | public static class Parameters
31 | {
32 | public const string Error = "error";
33 | public const string ErrorDescription = "error_description";
34 | public const string ErrorUri = "error_uri";
35 | public const string Realm = "realm";
36 | public const string Scope = "scope";
37 | }
38 |
39 | public static class Properties
40 | {
41 | public const string Audiences = ".audiences";
42 | public const string Error = ".error";
43 | public const string ErrorDescription = ".error_description";
44 | public const string ErrorUri = ".error_uri";
45 | public const string Realm = ".realm";
46 | public const string Scope = ".scope";
47 | public const string Scopes = ".scopes";
48 | public const string Token = "access_token";
49 | }
50 |
51 | public static class Schemes
52 | {
53 | public const string Bearer = "Bearer";
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationDefaults.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace Owin.Security.OAuth.Validation
8 | {
9 | public static class OAuthValidationDefaults
10 | {
11 | ///
12 | /// Gets the default scheme used by the validation middleware.
13 | ///
14 | public const string AuthenticationScheme = "Bearer";
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationError.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | namespace Owin.Security.OAuth.Validation
8 | {
9 | ///
10 | /// Represents an OAuth2 validation error.
11 | ///
12 | public class OAuthValidationError
13 | {
14 | ///
15 | /// Gets or sets the error code.
16 | ///
17 | public string Error { get; set; }
18 |
19 | ///
20 | /// Gets or sets the error_description.
21 | ///
22 | public string ErrorDescription { get; set; }
23 |
24 | ///
25 | /// Gets or sets the error_uri.
26 | ///
27 | public string ErrorUri { get; set; }
28 |
29 | ///
30 | /// Gets or sets the realm.
31 | ///
32 | public string Realm { get; set; }
33 |
34 | ///
35 | /// Gets or sets the scope.
36 | ///
37 | public string Scope { get; set; }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationEvents.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Threading.Tasks;
9 |
10 | namespace Owin.Security.OAuth.Validation
11 | {
12 | ///
13 | /// Allows customization of validation handling within the middleware.
14 | ///
15 | public class OAuthValidationEvents
16 | {
17 | ///
18 | /// Invoked when a challenge response is returned to the caller.
19 | ///
20 | public Func OnApplyChallenge { get; set; } = context => Task.CompletedTask;
21 |
22 | ///
23 | /// Invoked when a ticket is to be created from an access token.
24 | ///
25 | public Func OnCreateTicket { get; set; } = context => Task.CompletedTask;
26 |
27 | ///
28 | /// Invoked when a token is to be decrypted.
29 | ///
30 | public Func OnDecryptToken { get; set; } = context => Task.CompletedTask;
31 |
32 | ///
33 | /// Invoked when a token is to be parsed from a newly-received request.
34 | ///
35 | public Func OnRetrieveToken { get; set; } = context => Task.CompletedTask;
36 |
37 | ///
38 | /// Invoked when a token is to be validated, before final processing.
39 | ///
40 | public Func OnValidateToken { get; set; } = context => Task.CompletedTask;
41 |
42 | ///
43 | /// Invoked when a challenge response is returned to the caller.
44 | ///
45 | public virtual Task ApplyChallenge(ApplyChallengeContext context) => OnApplyChallenge(context);
46 |
47 | ///
48 | /// Invoked when a ticket is to be created from an access token.
49 | ///
50 | public virtual Task CreateTicket(CreateTicketContext context) => OnCreateTicket(context);
51 |
52 | ///
53 | /// Invoked when a token is to be decrypted.
54 | ///
55 | public virtual Task DecryptToken(DecryptTokenContext context) => OnDecryptToken(context);
56 |
57 | ///
58 | /// Invoked when a token is to be parsed from a newly-received request.
59 | ///
60 | public virtual Task RetrieveToken(RetrieveTokenContext context) => OnRetrieveToken(context);
61 |
62 | ///
63 | /// Invoked when a token is to be validated, before final processing.
64 | ///
65 | public virtual Task ValidateToken(ValidateTokenContext context) => OnValidateToken(context);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationExtensions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using JetBrains.Annotations;
9 | using Microsoft.Extensions.Logging;
10 | using Owin.Security.OAuth.Validation;
11 |
12 | namespace Owin
13 | {
14 | ///
15 | /// Provides extension methods used to configure the OAuth2
16 | /// validation middleware in an OWIN/Katana pipeline.
17 | ///
18 | public static class OAuthValidationExtensions
19 | {
20 | ///
21 | /// Adds a new instance of the OAuth2 validation middleware in the OWIN/Katana pipeline.
22 | ///
23 | /// The application builder.
24 | /// The application builder.
25 | public static IAppBuilder UseOAuthValidation([NotNull] this IAppBuilder app)
26 | {
27 | if (app == null)
28 | {
29 | throw new ArgumentNullException(nameof(app));
30 | }
31 |
32 | return app.UseOAuthValidation(options => { });
33 | }
34 |
35 | ///
36 | /// Adds a new instance of the OAuth2 validation middleware in the OWIN/Katana pipeline.
37 | ///
38 | /// The application builder.
39 | /// The delegate used to configure the validation options.
40 | /// The application builder.
41 | public static IAppBuilder UseOAuthValidation(
42 | [NotNull] this IAppBuilder app,
43 | [NotNull] Action configuration)
44 | {
45 | if (app == null)
46 | {
47 | throw new ArgumentNullException(nameof(app));
48 | }
49 |
50 | if (configuration == null)
51 | {
52 | throw new ArgumentNullException(nameof(configuration));
53 | }
54 |
55 | var options = new OAuthValidationOptions();
56 | configuration(options);
57 |
58 | return app.UseOAuthValidation(options);
59 | }
60 |
61 | ///
62 | /// Adds a new instance of the OAuth2 validation middleware in the OWIN/Katana pipeline.
63 | ///
64 | /// The application builder.
65 | /// The options used to configure the validation middleware.
66 | /// The application builder.
67 | public static IAppBuilder UseOAuthValidation(
68 | [NotNull] this IAppBuilder app,
69 | [NotNull] OAuthValidationOptions options)
70 | {
71 | if (app == null)
72 | {
73 | throw new ArgumentNullException(nameof(app));
74 | }
75 |
76 | if (options == null)
77 | {
78 | throw new ArgumentNullException(nameof(options));
79 | }
80 |
81 | return app.Use(app.Properties, options);
82 | }
83 |
84 | ///
85 | /// Configures the OAuth2 validation middleware to enable logging.
86 | ///
87 | /// The options used to configure the OAuth2 validation middleware.
88 | /// The delegate used to configure the logger factory.
89 | /// The options used to configure the OAuth2 validation middleware.
90 | public static OAuthValidationOptions UseLogging(
91 | [NotNull] this OAuthValidationOptions options,
92 | [NotNull] Action configuration)
93 | {
94 | if (options == null)
95 | {
96 | throw new ArgumentNullException(nameof(options));
97 | }
98 |
99 | if (configuration == null)
100 | {
101 | throw new ArgumentNullException(nameof(configuration));
102 | }
103 |
104 | var factory = new LoggerFactory();
105 | configuration(factory);
106 |
107 | options.Logger = factory.CreateLogger();
108 |
109 | return options;
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationHelpers.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using JetBrains.Annotations;
9 | using Microsoft.Owin.Security;
10 |
11 | namespace Owin.Security.OAuth.Validation
12 | {
13 | ///
14 | /// Defines a set of commonly used helpers.
15 | ///
16 | internal static class OAuthValidationHelpers
17 | {
18 | ///
19 | /// Gets a given property from the authentication properties.
20 | ///
21 | /// The authentication properties.
22 | /// The specific property to look for.
23 | /// The value corresponding to the property, or null if the property cannot be found.
24 | public static string GetProperty([NotNull] this AuthenticationProperties properties, [NotNull] string property)
25 | {
26 | if (properties == null)
27 | {
28 | throw new ArgumentNullException(nameof(properties));
29 | }
30 |
31 | if (string.IsNullOrEmpty(property))
32 | {
33 | throw new ArgumentException("The property name cannot be null or empty.", nameof(property));
34 | }
35 |
36 | if (!properties.Dictionary.TryGetValue(property, out string value))
37 | {
38 | return null;
39 | }
40 |
41 | return value;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationMiddleware.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using JetBrains.Annotations;
10 | using Microsoft.AspNetCore.DataProtection;
11 | using Microsoft.Extensions.Logging.Abstractions;
12 | using Microsoft.Owin;
13 | using Microsoft.Owin.BuilderProperties;
14 | using Microsoft.Owin.Security.Infrastructure;
15 | using Microsoft.Owin.Security.Interop;
16 |
17 | namespace Owin.Security.OAuth.Validation
18 | {
19 | ///
20 | /// Provides the entry point necessary to register the
21 | /// OAuth2 validation handler in an OWIN/Katana pipeline.
22 | ///
23 | public class OAuthValidationMiddleware : AuthenticationMiddleware
24 | {
25 | ///
26 | /// Creates a new instance of the class.
27 | ///
28 | public OAuthValidationMiddleware(
29 | [NotNull] OwinMiddleware next,
30 | [NotNull] IDictionary properties,
31 | [NotNull] OAuthValidationOptions options)
32 | : base(next, options)
33 | {
34 | if (Options.Events == null)
35 | {
36 | Options.Events = new OAuthValidationEvents();
37 | }
38 |
39 | if (options.DataProtectionProvider == null)
40 | {
41 | // Use the application name provided by the OWIN host as the Data Protection discriminator.
42 | // If the application name cannot be resolved, throw an invalid operation exception.
43 | var discriminator = new AppProperties(properties).AppName;
44 | if (string.IsNullOrEmpty(discriminator))
45 | {
46 | throw new InvalidOperationException("The application name cannot be resolved from the OWIN application builder. " +
47 | "Consider manually setting the 'DataProtectionProvider' property in the " +
48 | "options using 'DataProtectionProvider.Create([unique application name])'.");
49 | }
50 |
51 | options.DataProtectionProvider = DataProtectionProvider.Create(discriminator);
52 | }
53 |
54 | if (options.AccessTokenFormat == null)
55 | {
56 | // Note: the following purposes must match the ones used by the OpenID Connect server middleware.
57 | var protector = Options.DataProtectionProvider.CreateProtector(
58 | "OpenIdConnectServerHandler", nameof(Options.AccessTokenFormat), "ASOS");
59 |
60 | options.AccessTokenFormat = new AspNetTicketDataFormat(new DataProtectorShim(protector));
61 | }
62 |
63 | if (options.Logger == null)
64 | {
65 | options.Logger = NullLogger.Instance;
66 | }
67 | }
68 |
69 | ///
70 | /// Returns a new instance.
71 | ///
72 | /// A new instance of the class.
73 | protected override AuthenticationHandler CreateHandler()
74 | {
75 | return new OAuthValidationHandler();
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/OAuthValidationOptions.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Collections.Generic;
9 | using Microsoft.AspNetCore.DataProtection;
10 | using Microsoft.Extensions.Logging;
11 | using Microsoft.Owin.Infrastructure;
12 | using Microsoft.Owin.Security;
13 |
14 | namespace Owin.Security.OAuth.Validation
15 | {
16 | ///
17 | /// Exposes various settings needed to control
18 | /// the behavior of the validation middleware.
19 | ///
20 | public class OAuthValidationOptions : AuthenticationOptions
21 | {
22 | ///
23 | /// Creates a new instance of the class.
24 | ///
25 | public OAuthValidationOptions()
26 | : base(OAuthValidationDefaults.AuthenticationScheme)
27 | {
28 | AuthenticationMode = AuthenticationMode.Active;
29 | }
30 |
31 | ///
32 | /// Gets the intended audiences of this resource server.
33 | /// Setting this property is recommended when the authorization
34 | /// server issues access tokens for multiple distinct resource servers.
35 | ///
36 | public ISet Audiences { get; } = new HashSet(StringComparer.Ordinal);
37 |
38 | ///
39 | /// Gets or sets the optional "realm" value returned to
40 | /// the caller as part of the WWW-Authenticate header.
41 | ///
42 | public string Realm { get; set; }
43 |
44 | ///
45 | /// Gets or sets a boolean determining whether the access token should be stored in the
46 | /// after a successful authentication process.
47 | ///
48 | public bool SaveToken { get; set; } = true;
49 |
50 | ///
51 | /// Gets or sets a boolean determining whether the token validation errors should be returned to the caller.
52 | /// Enabled by default, this option can be disabled to prevent the validation middleware from returning
53 | /// an error, an error_description and/or an error_uri in the WWW-Authenticate header.
54 | ///
55 | public bool IncludeErrorDetails { get; set; } = true;
56 |
57 | ///
58 | /// Gets or sets the logger used by the OAuth2 validation handler.
59 | /// When unassigned, a default instance is created using the logger factory.
60 | ///
61 | public ILogger Logger { get; set; }
62 |
63 | ///
64 | /// Gets or sets the clock used to determine the current date/time.
65 | ///
66 | public ISystemClock SystemClock { get; set; } = new SystemClock();
67 |
68 | ///
69 | /// Gets or sets the data format used to unprotect the
70 | /// access tokens received by the validation middleware.
71 | ///
72 | public ISecureDataFormat AccessTokenFormat { get; set; }
73 |
74 | ///
75 | /// Gets or sets the data protection provider used to create the default
76 | /// data protector used by the OAuth2 validation handler.
77 | ///
78 | public IDataProtectionProvider DataProtectionProvider { get; set; }
79 |
80 | ///
81 | /// Gets or sets the object provided by the application to process events raised by the authentication middleware.
82 | /// The application may implement the interface fully, or it may create an instance of
83 | /// and assign delegates only to the events it wants to process.
84 | ///
85 | public OAuthValidationEvents Events { get; set; } = new OAuthValidationEvents();
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/Owin.Security.OAuth.Validation/Owin.Security.OAuth.Validation.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net461
7 |
8 |
9 |
10 | OAuth2 validation middleware for OWIN/Katana.
11 | Kévin Chalet
12 | authentication;katana;jwt;openidconnect;owin;security
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/test/AspNet.Security.OAuth.Introspection.Tests/AspNet.Security.OAuth.Introspection.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | netcoreapp2.0;net461
7 | netcoreapp2.0
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/test/AspNet.Security.OAuth.Introspection.Tests/OAuthIntrospectionInitializerTests.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Threading.Tasks;
9 | using Microsoft.AspNetCore.Authentication;
10 | using Microsoft.AspNetCore.Builder;
11 | using Microsoft.AspNetCore.DataProtection;
12 | using Microsoft.AspNetCore.Hosting;
13 | using Microsoft.AspNetCore.TestHost;
14 | using Microsoft.Extensions.DependencyInjection;
15 | using Microsoft.Extensions.Logging;
16 | using Xunit;
17 |
18 | namespace AspNet.Security.OAuth.Introspection.Tests
19 | {
20 | public class OAuthIntrospectionInitializerTests
21 | {
22 | [Theory]
23 | [InlineData(null, null)]
24 | [InlineData("", "")]
25 | [InlineData("client_id", null)]
26 | [InlineData("client_id", "")]
27 | [InlineData(null, "client_secret")]
28 | [InlineData("", "client_secret")]
29 | public async Task PostConfigure_ThrowsAnExceptionForMissingCredentials(string identifier, string secret)
30 | {
31 | // Arrange
32 | var server = CreateResourceServer(options =>
33 | {
34 | options.Authority = new Uri("http://www.fabrikam.com/");
35 | options.ClientId = identifier;
36 | options.ClientSecret = secret;
37 | options.RequireHttpsMetadata = false;
38 | });
39 |
40 | var client = server.CreateClient();
41 |
42 | // Act and assert
43 | var exception = await Assert.ThrowsAsync(delegate
44 | {
45 | return client.GetAsync("/");
46 | });
47 |
48 | Assert.Equal("Client credentials must be configured.", exception.Message);
49 | }
50 |
51 | [Fact]
52 | public async Task PostConfigure_ThrowsAnExceptionForMissingEndpoint()
53 | {
54 | // Arrange
55 | var server = CreateResourceServer(options =>
56 | {
57 | options.Configuration = new OAuthIntrospectionConfiguration
58 | {
59 | IntrospectionEndpoint = null
60 | };
61 | });
62 |
63 | var client = server.CreateClient();
64 |
65 | // Act and assert
66 | var exception = await Assert.ThrowsAsync(delegate
67 | {
68 | return client.GetAsync("/");
69 | });
70 |
71 | Assert.Equal("The introspection endpoint address cannot be null or empty.", exception.Message);
72 | }
73 |
74 | [Fact]
75 | public async Task PostConfigure_ThrowsAnExceptionForMissingAuthority()
76 | {
77 | // Arrange
78 | var server = CreateResourceServer(options =>
79 | {
80 | options.Authority = null;
81 | options.MetadataAddress = null;
82 | });
83 |
84 | var client = server.CreateClient();
85 |
86 | // Act and assert
87 | var exception = await Assert.ThrowsAsync(delegate
88 | {
89 | return client.GetAsync("/");
90 | });
91 |
92 | Assert.Equal("The authority or an absolute metadata endpoint address must be provided.", exception.Message);
93 | }
94 |
95 | [Fact]
96 | public async Task PostConfigure_ThrowsAnExceptionForRelativeAuthority()
97 | {
98 | // Arrange
99 | var server = CreateResourceServer(options =>
100 | {
101 | options.Authority = new Uri("/relative-path", UriKind.Relative);
102 | });
103 |
104 | var client = server.CreateClient();
105 |
106 | // Act and assert
107 | var exception = await Assert.ThrowsAsync(delegate
108 | {
109 | return client.GetAsync("/");
110 | });
111 |
112 | Assert.Equal("The authority must be provided and must be an absolute URL.", exception.Message);
113 | }
114 |
115 | [Theory]
116 | [InlineData("http://www.fabrikam.com/path?param=value")]
117 | [InlineData("http://www.fabrikam.com/path#param=value")]
118 | public async Task PostConfigure_ThrowsAnExceptionForInvalidAuthority(string authority)
119 | {
120 | // Arrange
121 | var server = CreateResourceServer(options =>
122 | {
123 | options.Authority = new Uri(authority);
124 | });
125 |
126 | var client = server.CreateClient();
127 |
128 | // Act and assert
129 | var exception = await Assert.ThrowsAsync(delegate
130 | {
131 | return client.GetAsync("/");
132 | });
133 |
134 | Assert.Equal("The authority cannot contain a fragment or a query string.", exception.Message);
135 | }
136 |
137 | [Fact]
138 | public async Task PostConfigure_ThrowsAnExceptionForNonHttpsAuthority()
139 | {
140 | // Arrange
141 | var server = CreateResourceServer(options =>
142 | {
143 | options.Authority = new Uri("http://www.fabrikam.com/");
144 | options.RequireHttpsMetadata = true;
145 | });
146 |
147 | var client = server.CreateClient();
148 |
149 | // Act and assert
150 | var exception = await Assert.ThrowsAsync(delegate
151 | {
152 | return client.GetAsync("/");
153 | });
154 |
155 | Assert.Equal("The metadata endpoint address must be a HTTPS URL when " +
156 | "'RequireHttpsMetadata' is not set to 'false'.", exception.Message);
157 | }
158 |
159 | private static TestServer CreateResourceServer(Action configuration = null)
160 | {
161 | var builder = new WebHostBuilder();
162 | builder.UseEnvironment("Testing");
163 |
164 | builder.ConfigureLogging(options => options.AddDebug());
165 |
166 | builder.ConfigureServices(services =>
167 | {
168 | services.AddDistributedMemoryCache();
169 |
170 | services.AddAuthentication()
171 | .AddOAuthIntrospection(options =>
172 | {
173 | options.ClientId = "Fabrikam";
174 | options.ClientSecret = "B4657E03-D619";
175 |
176 | // Note: overriding the default data protection provider is not necessary for the tests to pass,
177 | // but is useful to ensure unnecessary keys are not persisted in testing environments, which also
178 | // helps make the unit tests run faster, as no registry or disk access is required in this case.
179 | options.DataProtectionProvider = new EphemeralDataProtectionProvider(new LoggerFactory());
180 |
181 | // Run the configuration delegate
182 | // registered by the unit tests.
183 | configuration?.Invoke(options);
184 | });
185 | });
186 |
187 | builder.Configure(app =>
188 | {
189 | app.Run(context => context.ChallengeAsync(OAuthIntrospectionDefaults.AuthenticationScheme));
190 | });
191 |
192 | return new TestServer(builder);
193 | }
194 | }
195 | }
196 |
--------------------------------------------------------------------------------
/test/AspNet.Security.OAuth.Validation.Tests/AspNet.Security.OAuth.Validation.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | netcoreapp2.0;net461
7 | netcoreapp2.0
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/test/Owin.Security.OAuth.Introspection.Tests/OAuthIntrospectionMiddlewareTests.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Reflection;
9 | using Microsoft.AspNetCore.DataProtection;
10 | using Microsoft.Extensions.Logging;
11 | using Microsoft.Owin.BuilderProperties;
12 | using Microsoft.Owin.Testing;
13 | using Xunit;
14 |
15 | namespace Owin.Security.OAuth.Introspection.Tests
16 | {
17 | public class OAuthIntrospectionMiddlewareTests
18 | {
19 | [Theory]
20 | [InlineData(null, null)]
21 | [InlineData("", "")]
22 | [InlineData("client_id", null)]
23 | [InlineData("client_id", "")]
24 | [InlineData(null, "client_secret")]
25 | [InlineData("", "client_secret")]
26 | public void Constructor_ThrowsAnExceptionForMissingCredentials(string identifier, string secret)
27 | {
28 | // Arrange, act, assert
29 | var exception = Assert.Throws(() => CreateResourceServer(options =>
30 | {
31 | options.Authority = new Uri("http://www.fabrikam.com/");
32 | options.ClientId = identifier;
33 | options.ClientSecret = secret;
34 | options.RequireHttpsMetadata = false;
35 | }));
36 |
37 | Assert.IsType(exception.InnerException);
38 | Assert.Equal("options", ((ArgumentException) exception.InnerException).ParamName);
39 | Assert.StartsWith("Client credentials must be configured.", exception.InnerException.Message);
40 | }
41 |
42 | [Theory]
43 | [InlineData(null)]
44 | [InlineData("")]
45 | public void Constructor_ThrowsAnExceptionForMissingAppName(string name)
46 | {
47 | // Arrange, act, assert
48 | var exception = Assert.Throws(() => TestServer.Create(app =>
49 | {
50 | var properties = new AppProperties(app.Properties);
51 | properties.AppName = name;
52 |
53 | app.UseOAuthIntrospection(options =>
54 | {
55 | options.Authority = new Uri("http://www.fabrikam.com/");
56 | options.ClientId = "Fabrikam";
57 | options.ClientSecret = "B4657E03-D619";
58 | options.RequireHttpsMetadata = false;
59 | });
60 | }));
61 |
62 | Assert.IsType(exception.InnerException);
63 | Assert.StartsWith("The application name cannot be resolved from the OWIN application builder. " +
64 | "Consider manually setting the 'DataProtectionProvider' property in the " +
65 | "options using 'DataProtectionProvider.Create([unique application name])'.",
66 | exception.InnerException.Message);
67 | }
68 |
69 | [Fact]
70 | public void Constructor_ThrowsAnExceptionForMissingEndpoint()
71 | {
72 | // Arrange, act, assert
73 | var exception = Assert.Throws(() => CreateResourceServer(options =>
74 | {
75 | options.Configuration = new OAuthIntrospectionConfiguration
76 | {
77 | IntrospectionEndpoint = null
78 | };
79 | }));
80 |
81 | Assert.IsType(exception.InnerException);
82 | Assert.Equal("options", ((ArgumentException) exception.InnerException).ParamName);
83 | Assert.StartsWith("The introspection endpoint address cannot be null or empty.", exception.InnerException.Message);
84 | }
85 |
86 | [Fact]
87 | public void Constructor_ThrowsAnExceptionForMissingAuthority()
88 | {
89 | // Arrange, act, assert
90 | var exception = Assert.Throws(() => CreateResourceServer(options =>
91 | {
92 | options.Authority = null;
93 | options.MetadataAddress = null;
94 | }));
95 |
96 | Assert.IsType(exception.InnerException);
97 | Assert.Equal("options", ((ArgumentException) exception.InnerException).ParamName);
98 | Assert.StartsWith("The authority or an absolute metadata endpoint address must be provided.", exception.InnerException.Message);
99 | }
100 |
101 | [Fact]
102 | public void Constructor_ThrowsAnExceptionForRelativeAuthority()
103 | {
104 | // Arrange, act, assert
105 | var exception = Assert.Throws(() => CreateResourceServer(options =>
106 | {
107 | options.Authority = new Uri("/relative-path", UriKind.Relative);
108 | }));
109 |
110 | Assert.IsType(exception.InnerException);
111 | Assert.Equal("options", ((ArgumentException) exception.InnerException).ParamName);
112 | Assert.StartsWith("The authority must be provided and must be an absolute URL.", exception.InnerException.Message);
113 | }
114 |
115 | [Theory]
116 | [InlineData("http://www.fabrikam.com/path?param=value")]
117 | [InlineData("http://www.fabrikam.com/path#param=value")]
118 | public void Constructor_ThrowsAnExceptionForInvalidAuthority(string authority)
119 | {
120 | // Arrange, act, assert
121 | var exception = Assert.Throws(() => CreateResourceServer(options =>
122 | {
123 | options.Authority = new Uri(authority);
124 | }));
125 |
126 | Assert.IsType(exception.InnerException);
127 | Assert.Equal("options", ((ArgumentException) exception.InnerException).ParamName);
128 | Assert.StartsWith("The authority cannot contain a fragment or a query string.", exception.InnerException.Message);
129 | }
130 |
131 | [Fact]
132 | public void Constructor_ThrowsAnExceptionForNonHttpsAuthority()
133 | {
134 | // Arrange, act, assert
135 | var exception = Assert.Throws(() => CreateResourceServer(options =>
136 | {
137 | options.Authority = new Uri("http://www.fabrikam.com/");
138 | options.RequireHttpsMetadata = true;
139 | }));
140 |
141 | Assert.IsType(exception.InnerException);
142 | Assert.Equal("options", ((ArgumentException) exception.InnerException).ParamName);
143 | Assert.StartsWith("The metadata endpoint address must be a HTTPS URL when " +
144 | "'RequireHttpsMetadata' is not set to 'false'.", exception.InnerException.Message);
145 | }
146 |
147 | private static TestServer CreateResourceServer(Action configuration = null)
148 | {
149 | return TestServer.Create(app =>
150 | {
151 | app.UseOAuthIntrospection(options =>
152 | {
153 | options.Authority = new Uri("http://www.fabrikam.com/");
154 | options.RequireHttpsMetadata = false;
155 |
156 | options.ClientId = "Fabrikam";
157 | options.ClientSecret = "B4657E03-D619";
158 |
159 | // Note: overriding the default data protection provider is not necessary for the tests to pass,
160 | // but is useful to ensure unnecessary keys are not persisted in testing environments, which also
161 | // helps make the unit tests run faster, as no registry or disk access is required in this case.
162 | options.DataProtectionProvider = new EphemeralDataProtectionProvider(new LoggerFactory());
163 |
164 | // Run the configuration delegate
165 | // registered by the unit tests.
166 | configuration?.Invoke(options);
167 | });
168 | });
169 | }
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/test/Owin.Security.OAuth.Introspection.Tests/Owin.Security.OAuth.Introspection.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net461
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/test/Owin.Security.OAuth.Validation.Tests/OAuthValidationMiddlewareTests.cs:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0)
3 | * See https://github.com/aspnet-contrib/AspNet.Security.OAuth.Extensions for more information
4 | * concerning the license and the contributors participating to this project.
5 | */
6 |
7 | using System;
8 | using System.Reflection;
9 | using Microsoft.Owin.BuilderProperties;
10 | using Microsoft.Owin.Testing;
11 | using Xunit;
12 |
13 | namespace Owin.Security.OAuth.Validation.Tests
14 | {
15 | public class OAuthValidationMiddlewareTests
16 | {
17 | [Theory]
18 | [InlineData(null)]
19 | [InlineData("")]
20 | public void Constructor_ThrowsAnExceptionForMissingAppName(string name)
21 | {
22 | // Arrange, act, assert
23 | var exception = Assert.Throws(() => TestServer.Create(app =>
24 | {
25 | var properties = new AppProperties(app.Properties);
26 | properties.AppName = name;
27 |
28 | app.UseOAuthValidation();
29 | }));
30 |
31 | Assert.IsType(exception.InnerException);
32 | Assert.StartsWith("The application name cannot be resolved from the OWIN application builder. " +
33 | "Consider manually setting the 'DataProtectionProvider' property in the " +
34 | "options using 'DataProtectionProvider.Create([unique application name])'.",
35 | exception.InnerException.Message);
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/test/Owin.Security.OAuth.Validation.Tests/Owin.Security.OAuth.Validation.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | net461
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------