Compare commits

...

28 Commits

Author SHA1 Message Date
Tommy Parnell
22c830dbfb bump version 2018-05-01 19:51:22 -04:00
Tommy Parnell
06457050a8 Merge pull request #236 from JPRuskin/patch-1
Update Steam OpenID Regex to handle HTTPS
2018-05-01 19:50:30 -04:00
James Ruskin
35ea1c9d79 Update Steam OpenID Regex to handle HTTPS
Steam have updated their implementation to return https URIs in claimedID (please see [this thread](https://www.reddit.com/r/Steam/comments/8a7gsu/steam_openid_broken_for_many_websites_fix_inside/)).

The current version of the `_accountIDRegex` does not handle this.

This change should fix this. Arguably, we should not include the option to accept http, as Steam have (seemingly) irrevocably changed this.

This should solve [Issue #234](https://github.com/TerribleDev/OwinOAuthProviders/issues/234).
2018-04-30 11:49:04 +01:00
Tommy Parnell
900c80a98f bump version 2018-04-01 02:25:35 -04:00
Wouter Van Speybroeck
f60e8b5ffa NameIDentifier should use Id from context instead of username (#232) 2018-04-01 02:25:11 -04:00
Tommy Parnell
c74cd15808 bump version 2018-03-06 21:24:46 -05:00
imaleksandr
26a690060a The "v" parameter with version number becomes obligatory for all API requests. An error will be returned if the parameter is not sent. (#228) 2018-03-06 21:24:17 -05:00
Tommy Parnell
113692b2e0 2.20.0 2018-02-20 21:33:30 -05:00
Ștefan Negrițoiu
88bf254a7b introduce Typeform OAuth provider (#226)
* add Option to specify Production vs. Sandbox Environment

also fixes issue
https://github.com/TerribleDev/OwinOAuthProviders/issues/54

* ability to specify Production vs. Sandbox environment per auth session in addition to global setting

* add examples to show usage of new Production vs. Sandbox Option for Salesforce provider

* initial commit for Typeform provider

* add Typeform project to solution

* use GUID for UserId and add warning regaring use for authentication
2018-02-20 21:30:58 -05:00
bernardocotta
38aa4bbed2 Fixed LinkedIn authorization and token endpoints. (#224)
* Changed LinkedInAuthenticationHandler to use the endpoints described at the documentation.

The authorization code generated by the old endpoint is not supported by the Recommended Jobs API.
2018-02-20 21:29:12 -05:00
Tommy Parnell
29be30bfd7 bump version 2017-12-29 01:58:14 -05:00
Tommy Parnell
b8055739ff rm semicolon 2017-12-29 01:57:41 -05:00
Ștefan Negrițoiu
7aeca07f08 Salesforce provider: add Option to specify Production vs. Sandbox environment (#223)
* add Option to specify Production vs. Sandbox Environment

also fixes issue
https://github.com/TerribleDev/OwinOAuthProviders/issues/54

* ability to specify Production vs. Sandbox environment per auth session in addition to global setting

* add examples to show usage of new Production vs. Sandbox Option for Salesforce provider
2017-12-29 01:56:14 -05:00
Tommy Parnell
fde4b5ebac fix rake 2017-12-08 11:20:09 -05:00
Tommy Parnell
d5b81fae9c fix sln 2017-12-08 10:51:14 -05:00
Tommy Parnell
bbd9e33570 bump version 2017-12-08 10:38:01 -05:00
Gavin Harriss
7bdabb4cb7 ArcGIS Portal provider (#214)
* ArcGIS Portal provider added
Originally attempted to inherit from ArcGIS Online provider, but a fair amount of refactoring is required to allow inheritance for everything that needs changing. To be revisited when time allows.
2017-12-08 10:37:16 -05:00
KB
91dbf99949 Change LangVersion to 6. #217 (#221) 2017-12-01 17:22:30 -05:00
Tommy Parnell
b4bd9587dc bump version 2017-11-03 00:42:48 -04:00
Joseph Pisano
43ee292d0c I added an auth provider for the Podbean API. (#218)
* Added the podbean auth provider.

* Updated Readme to include podbean

* Fixed Owin nuget reference

* Removed regions from around using statements, corrected the VS version in the solution file and changed the Startup.Auth in the demo project to use spaces instead of tabs.

* Added the OAuth refresh token to the PodbeanAuthenticatedContext.
2017-11-03 00:40:41 -04:00
Tommy Parnell
b351a6bf0f bump version 2017-10-13 09:42:25 -04:00
AlastairBateman
49e1126bc7 Updating DropboxAuthenticatedContext.cs and DropboxAuthennticationHandler.cs to use the Dropbox v2 API as they're shutting down their v1 API: https://blogs.dropbox.com/developers/2017/09/api-v1-shutdown-details/ (#216)
As per issue: https://github.com/TerribleDev/OwinOAuthProviders/issues/215
2017-10-13 09:32:16 -04:00
Hoku Kim
ba08bffec3 Added LinkedInAuthenticationOptions.Proxy host for web applications running behind a proxy. This allows the middleware to authenticate for the proxy request host instead of the application request host. (#213) 2017-10-13 09:32:06 -04:00
Tommy Parnell
9bb2a75712 remove unused file 2017-07-16 11:48:21 -04:00
Tommy Parnell
60f3438ce7 strong name all the things 2017-07-16 11:48:03 -04:00
Tommy Parnell
346facbe2f bump version 2017-05-19 17:05:23 -04:00
bkrupa
934d75e9ad Added ability to force verify on twitch authentication (#202) 2017-05-19 16:52:05 -04:00
bencurthoys
feba5cc2fb PayPal TLS Fix (#206)
* PayPal TLS Fix

PayPal requires TLS 1.2 now - Added comments explaining this is the
case, and additional error handling for when the callback fails when TLS
1.0 or 1.1 is set.

* Removed Sandbox Credentials

Tch.

* Changed exception to WebException

If the PayPalAuthenticationHandler sees that an error caused by the
wrong SecurityProtocol has occurred, it throws a new WebException
instead of just Exception

* Reverted Whitespace changes to Startup.Auth.cs

Whitespace somehow got changed. I think this reverts it.
2017-05-19 16:51:53 -04:00
122 changed files with 3874 additions and 291 deletions

View File

@@ -1,17 +1,17 @@
GEM
remote: http://rubygems.org/
specs:
albacore (2.0.4)
albacore (3.0.1)
map (~> 6.5)
nokogiri (~> 1.5)
rake (> 10)
rake (~> 10)
semver2 (~> 3.4)
map (6.6.0)
mini_portile2 (2.0.0)
nokogiri (1.6.7.2-x64-mingw32)
mini_portile2 (~> 2.0.0.rc2)
os (0.9.6)
rake (11.1.1)
mini_portile2 (2.3.0)
nokogiri (1.8.2-x64-mingw32)
mini_portile2 (~> 2.3.0)
os (1.0.0)
rake (10.5.0)
semver2 (3.4.2)
PLATFORMS
@@ -23,4 +23,4 @@ DEPENDENCIES
os
BUNDLED WITH
1.12.1
1.13.7

View File

@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14
VisualStudioVersion = 14.0.25420.1
# Visual Studio 15
VisualStudioVersion = 15.0.26730.12
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.ArcGISOnline", "src\Owin.Security.Providers.ArcGISOnline\Owin.Security.Providers.ArcGISOnline.csproj", "{8A49FAEF-D365-4D25-942C-1CAD03845A5E}"
EndProject
@@ -108,6 +108,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Eve
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.WSO2", "src\Owin.Security.Providers.WSO2\Owin.Security.Providers.WSO2.csproj", "{8FD3A9CB-E684-42C0-A8BF-7746FDD3D43C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Podbean", "src\Owin.Security.Providers.Podbean\Owin.Security.Providers.Podbean.csproj", "{A7B95FD4-08AD-499F-B574-07560CC2A63F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.ArcGISPortal", "src\Owin.Security.Providers.ArcGISPortal\Owin.Security.Providers.ArcGISPortal.csproj", "{18547CA4-D7D3-43C2-81C2-A21FC8151A93}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Typeform", "src\Owin.Security.Providers.Typeform\Owin.Security.Providers.Typeform.csproj", "{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -326,8 +332,23 @@ Global
{8FD3A9CB-E684-42C0-A8BF-7746FDD3D43C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8FD3A9CB-E684-42C0-A8BF-7746FDD3D43C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8FD3A9CB-E684-42C0-A8BF-7746FDD3D43C}.Release|Any CPU.Build.0 = Release|Any CPU
{A7B95FD4-08AD-499F-B574-07560CC2A63F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A7B95FD4-08AD-499F-B574-07560CC2A63F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A7B95FD4-08AD-499F-B574-07560CC2A63F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A7B95FD4-08AD-499F-B574-07560CC2A63F}.Release|Any CPU.Build.0 = Release|Any CPU
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18547CA4-D7D3-43C2-81C2-A21FC8151A93}.Release|Any CPU.Build.0 = Release|Any CPU
{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EDFDB942-6583-4AD9-A868-B354B5BF07FC}
EndGlobalSection
EndGlobal

View File

@@ -3,6 +3,9 @@ using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Owin.Security.Providers.Evernote;
using Owin.Security.Providers.PayPal;
using Owin.Security.Providers.ArcGISPortal;
using Owin.Security.Providers.Typeform;
namespace OwinOAuthProvidersDemo
{
@@ -124,14 +127,50 @@ namespace OwinOAuthProvidersDemo
// clientId: "",
// clientSecret: "");
//in scenarios where a sandbox URL needs to be used
//var salesforceOptions = new SalesforceAuthenticationOptions
// Salesforce Option 1: don't specify explicit Endpoint config and use Production endpoint defaults
//var salesforceOptions1 = new SalesforceAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// Provider = new SalesforceAuthenticationProvider()
// {
// OnAuthenticated = async context =>
// {
// System.Diagnostics.Debug.WriteLine(context.AccessToken);
// System.Diagnostics.Debug.WriteLine(context.RefreshToken);
// System.Diagnostics.Debug.WriteLine(context.OrganizationId);
// }
// }
//};
// Salesforce Option 2: ask for Sandbox environment; no need to know what those endpoints are
//var salesforceOptions2 = new SalesforceAuthenticationOptions
//{
// Endpoints =
// new SalesforceAuthenticationOptions.SalesforceAuthenticationEndpoints
// {
// AuthorizationEndpoint =
// "https://ap1.salesforce.com/services/oauth2/authorize",
// Environment = Owin.Security.Providers.Salesforce.Constants.SandboxEnvironment
// },
// ClientId = "",
// ClientSecret = "",
// Provider = new SalesforceAuthenticationProvider()
// {
// OnAuthenticated = async context =>
// {
// System.Diagnostics.Debug.WriteLine(context.AccessToken);
// System.Diagnostics.Debug.WriteLine(context.RefreshToken);
// System.Diagnostics.Debug.WriteLine(context.OrganizationId);
// }
// }
//};
// Salesforce Option 3: explicitly specify endpoints (will take precedence over Environment choice)
//var salesforceOptions3 = new SalesforceAuthenticationOptions
//{
// Endpoints =
// new SalesforceAuthenticationOptions.SalesforceAuthenticationEndpoints
// {
// AuthorizationEndpoint = "https://ap1.salesforce.com/services/oauth2/authorize",
// TokenEndpoint = "https://ap1.salesforce.com/services/oauth2/token"
// },
// ClientId = "",
@@ -146,7 +185,7 @@ namespace OwinOAuthProvidersDemo
// }
// }
//};
//app.UseSalesforceAuthentication(salesforceOptions);
//app.UseSalesforceAuthentication(salesforceOptions1);
////app.UseShopifyAuthentication("", "");
@@ -154,6 +193,12 @@ namespace OwinOAuthProvidersDemo
// clientId: "",
// clientSecret: "");
//app.UseArcGISPortalAuthentication(new ArcGISPortalAuthenticationOptions(
// "My ArcGIS Portal",
// "https://arcgisportal.mydomain.com/",
// "",
// ""));
//app.UseWordPressAuthentication(
// clientId: "",
// clientSecret: "");
@@ -193,10 +238,20 @@ namespace OwinOAuthProvidersDemo
// clientId: "",
// clientSecret: "");
//app.UsePayPalAuthentication(
// clientId: "",
// clientSecret: "",
// isSandbox: false);
// PayPal no longer supports Tls 1.0 or 1.1
// https://devblog.paypal.com/upcoming-security-changes-notice/
// http://stackoverflow.com/questions/34939523/the-request-was-aborted-could-not-create-ssl-tls-secure-channel-sandbox-account
// System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol | System.Net.SecurityProtocolType.Tls12;
// The Return URL must be configured in the PayPal application to https://[hostname][:port]/signin-paypal
// PayPalAuthenticationOptions payPalOptions = new PayPalAuthenticationOptions(true);
// payPalOptions.ClientId = "";
// payPalOptions.ClientSecret = "";
// payPalOptions.Scope.Add("email");
// payPalOptions.Scope.Add("profile");
// payPalOptions.Scope.Add("address");
// payPalOptions.Scope.Add("https://uri.paypal.com/services/expresscheckout");
// app.UsePayPalAuthentication(payPalOptions);
//app.UseWargamingAccountAuthentication("", WargamingAuthenticationOptions.Region.NorthAmerica);
@@ -296,6 +351,24 @@ namespace OwinOAuthProvidersDemo
// AppKey = "",
// AppSecret = ""
//});
//app.UsePodbeanAuthentication(new PodbeanAuthenticationOptions
//{
// AppId = "",
// AppSecret = "",
// DebugUsingRequestHeadersToBuildBaseUri = true
//});
// WARNING:
// Typeform doesn't supply the user's ID so use this provider for authorization only, not authentication
// because each time you sign in with the same Typeform account it will yield a distinct UserId.
//var typeformOptions = new Owin.Security.Providers.Typeform.TypeformAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
//};
//typeformOptions.Scope.Add("forms:read");
//app.UseTypeformAuthentication(typeformOptions);
}
}
}

View File

@@ -419,6 +419,13 @@ namespace OwinOAuthProvidersDemo.Controllers
properties.Dictionary[ShopNameKey] = ShopName;
}
// if use Salesforce as OAuth provider you can ask for Sandbox auth endpoint
// for this particular request only
//properties.Dictionary.Add(
// Owin.Security.Providers.Salesforce.Constants.EnvironmentAuthenticationProperty,
// Owin.Security.Providers.Salesforce.Constants.SandboxEnvironment
// );
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);
}
}

View File

@@ -22,6 +22,7 @@
<IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
<UseGlobalApplicationHostFile />
<TargetFrameworkProfile />
<Use64BitIISExpress />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -31,6 +32,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -39,6 +41,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Antlr3.Runtime, Version=3.5.0.2, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
@@ -252,14 +255,226 @@
<Content Include="Scripts\jquery-2.2.3.min.map" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\base\Owin.Security.Providers.OpenIDBase\Owin.Security.Providers.OpenIDBase.csproj">
<Project>{4fd7b873-1994-4990-aa40-c37060121494}</Project>
<Name>Owin.Security.Providers.OpenIDBase</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.ArcGISOnline\Owin.Security.Providers.ArcGISOnline.csproj">
<Project>{8a49faef-d365-4d25-942c-1cad03845a5e}</Project>
<Name>Owin.Security.Providers.ArcGISOnline</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.ArcGISPortal\Owin.Security.Providers.ArcGISPortal.csproj">
<Project>{18547ca4-d7d3-43c2-81c2-a21fc8151a93}</Project>
<Name>Owin.Security.Providers.ArcGISPortal</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Asana\Owin.Security.Providers.Asana.csproj">
<Project>{f3e27220-1d8c-4037-94aa-7b7f4a12f351}</Project>
<Name>Owin.Security.Providers.Asana</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Backlog\Owin.Security.Providers.Backlog.csproj">
<Project>{2dc03778-9ef1-466a-83ec-7d8422decd23}</Project>
<Name>Owin.Security.Providers.Backlog</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Baidu\Owin.Security.Providers.Baidu.csproj">
<Project>{e2759807-4d7c-4288-aac8-f5b7b4616680}</Project>
<Name>Owin.Security.Providers.Baidu</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.BattleNet\Owin.Security.Providers.BattleNet.csproj">
<Project>{99a175da-ade4-436c-a272-c8ae44b7a086}</Project>
<Name>Owin.Security.Providers.BattleNet</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Bitbucket\Owin.Security.Providers.Bitbucket.csproj">
<Project>{e5212fc7-abcb-462f-9989-8e022dffe43c}</Project>
<Name>Owin.Security.Providers.Bitbucket</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Box\Owin.Security.Providers.Box.csproj">
<Project>{1aef8813-e1f9-41e1-bc8d-732960595e9f}</Project>
<Name>Owin.Security.Providers.Box</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Buffer\Owin.Security.Providers.Buffer.csproj">
<Project>{6f75fc1f-d9e9-49b3-a6ce-cfa8feea11a5}</Project>
<Name>Owin.Security.Providers.Buffer</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Cosign\Owin.Security.Providers.Cosign.csproj">
<Project>{1f1f8d6b-7219-46fa-93d3-8d3061a6cbbf}</Project>
<Name>Owin.Security.Providers.Cosign</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.DeviantArt\Owin.Security.Providers.DeviantArt.csproj">
<Project>{fabd2e54-976d-41f5-8800-dee58acc027c}</Project>
<Name>Owin.Security.Providers.DeviantArt</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Discord\Owin.Security.Providers.Discord.csproj">
<Project>{4be728eb-778a-41af-8dea-0c7159711d44}</Project>
<Name>Owin.Security.Providers.Discord</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.DoYouBuzz\Owin.Security.Providers.DoYouBuzz.csproj">
<Project>{4550d8bd-05a7-44f8-bbc0-c3d8e7af2912}</Project>
<Name>Owin.Security.Providers.DoYouBuzz</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Dropbox\Owin.Security.Providers.Dropbox.csproj">
<Project>{cef697b1-3651-49e5-9060-65f2e26c039c}</Project>
<Name>Owin.Security.Providers.Dropbox</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.EVEOnline\Owin.Security.Providers.EVEOnline.csproj">
<Project>{f5dc23f4-5042-4024-9e34-aca648602ba0}</Project>
<Name>Owin.Security.Providers.EVEOnline</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Evernote\Owin.Security.Providers.Evernote.csproj">
<Project>{b8f05057-8b9f-44ce-b983-99cb7c2e9e5a}</Project>
<Name>Owin.Security.Providers.Evernote</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Fitbit\Owin.Security.Providers.Fitbit.csproj">
<Project>{ca44d014-5a74-4749-a891-1f711fd3a266}</Project>
<Name>Owin.Security.Providers.Fitbit</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Flickr\Owin.Security.Providers.Flickr.csproj">
<Project>{af6cbeb8-5638-43d4-839e-c81f305960be}</Project>
<Name>Owin.Security.Providers.Flickr</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Foursquare\Owin.Security.Providers.Foursquare.csproj">
<Project>{8acd9194-1efe-4128-ac42-856d856332a4}</Project>
<Name>Owin.Security.Providers.Foursquare</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Geni\Owin.Security.Providers.Geni.csproj">
<Project>{9de25431-f935-48d7-8eb5-acb6f918111c}</Project>
<Name>Owin.Security.Providers.Geni</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.GitHub\Owin.Security.Providers.GitHub.csproj">
<Project>{803f9eb7-029c-45ac-ab81-135e60d5beae}</Project>
<Name>Owin.Security.Providers.GitHub</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Gitter\Owin.Security.Providers.Gitter.csproj">
<Project>{42ec50eb-0c51-460c-93a4-1e007bf1f323}</Project>
<Name>Owin.Security.Providers.Gitter</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.GooglePlus\Owin.Security.Providers.GooglePlus.csproj">
<Project>{d3fef959-0e0e-4f50-954c-f123a0b629dc}</Project>
<Name>Owin.Security.Providers.GooglePlus</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.HealthGraph\Owin.Security.Providers.HealthGraph.csproj">
<Project>{157bb715-29b2-4202-8a59-ccbacfcbedd3}</Project>
<Name>Owin.Security.Providers.HealthGraph</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Imgur\Owin.Security.Providers.Imgur.csproj">
<Project>{101841d3-645e-4a44-af8b-8aaa85ceea4e}</Project>
<Name>Owin.Security.Providers.Imgur</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Instagram\Owin.Security.Providers.Instagram.csproj">
<Project>{041178c4-6131-4d68-9896-ce33124d83a0}</Project>
<Name>Owin.Security.Providers.Instagram</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.LinkedIn\Owin.Security.Providers.LinkedIn.csproj">
<Project>{9fa87825-30e9-48d7-ac4a-39e8f0c2777c}</Project>
<Name>Owin.Security.Providers.LinkedIn</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.MyHeritage\Owin.Security.Providers.MyHeritage.csproj">
<Project>{84795078-31b5-4369-bd1b-f960165f8c71}</Project>
<Name>Owin.Security.Providers.MyHeritage</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Onshape\Owin.Security.Providers.Onshape.csproj">
<Project>{9fec99f8-6f45-40a2-8200-85381434c79a}</Project>
<Name>Owin.Security.Providers.Onshape</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.OpenID\Owin.Security.Providers.OpenID.csproj">
<Project>{90c152d7-9c66-4949-9998-c7ce48b593de}</Project>
<Name>Owin.Security.Providers.OpenID</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Orcid\Owin.Security.Providers.Orcid.csproj">
<Project>{89cb4342-e23d-4e7c-89e5-c369599a5860}</Project>
<Name>Owin.Security.Providers.Orcid</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.PayPal\Owin.Security.Providers.PayPal.csproj">
<Project>{f7129064-3db7-4b79-81d3-80130d664e45}</Project>
<Name>Owin.Security.Providers.PayPal</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Podbean\Owin.Security.Providers.Podbean.csproj">
<Project>{a7b95fd4-08ad-499f-b574-07560cc2a63f}</Project>
<Name>Owin.Security.Providers.Podbean</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Reddit\Owin.Security.Providers.Reddit.csproj">
<Project>{d0cd86c8-a6f9-4c6c-9bf0-eaa461e7fbad}</Project>
<Name>Owin.Security.Providers.Reddit</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Salesforce\Owin.Security.Providers.Salesforce.csproj">
<Project>{827a9d68-0dd4-4c5e-b763-8302faeedecc}</Project>
<Name>Owin.Security.Providers.Salesforce</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Shopify\Owin.Security.Providers.Shopify.csproj">
<Project>{67f12bfb-eb3a-4a86-b5dc-f4c066fdf792}</Project>
<Name>Owin.Security.Providers.Shopify</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.SlackProvider\Owin.Security.Providers.SlackProvider.csproj">
<Project>{3e6f293d-8500-428d-bdc9-27440cc91e16}</Project>
<Name>Owin.Security.Providers.SlackProvider</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.SoundCloud\Owin.Security.Providers.SoundCloud.csproj">
<Project>{2c959026-7058-4302-a6c4-dfd10a030585}</Project>
<Name>Owin.Security.Providers.SoundCloud</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Spotify\Owin.Security.Providers.Spotify.csproj">
<Project>{683b4041-a399-40ce-84b8-392f08a6805d}</Project>
<Name>Owin.Security.Providers.Spotify</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.StackExchange\Owin.Security.Providers.StackExchange.csproj">
<Project>{2c0e07ed-f26d-4ff8-8c3d-f760c09a2d5a}</Project>
<Name>Owin.Security.Providers.StackExchange</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Steam\Owin.Security.Providers.Steam.csproj">
<Project>{312c4ed7-8ca1-4723-9203-abc694dfdc7c}</Project>
<Name>Owin.Security.Providers.Steam</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.TripIt\Owin.Security.Providers.TripIt.csproj">
<Project>{b35e2616-dc00-48b4-bd58-7e23046257f1}</Project>
<Name>Owin.Security.Providers.TripIt</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Twitch\Owin.Security.Providers.Twitch.csproj">
<Project>{c3cf8734-6aac-4f59-9a3e-1cba8582cd48}</Project>
<Name>Owin.Security.Providers.Twitch</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Typeform\Owin.Security.Providers.Typeform.csproj">
<Project>{c8862b45-e1d1-4ab7-a83d-3a2fd2a22526}</Project>
<Name>Owin.Security.Providers.Typeform</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Untappd\Owin.Security.Providers.Untappd.csproj">
<Project>{3e89eca3-f4e7-4181-b26b-8250d5151044}</Project>
<Name>Owin.Security.Providers.Untappd</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Vimeo\Owin.Security.Providers.Vimeo.csproj">
<Project>{98ecc703-d651-4ead-a55d-aa3e903ae4d7}</Project>
<Name>Owin.Security.Providers.Vimeo</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.VisualStudio\Owin.Security.Providers.VisualStudio.csproj">
<Project>{3b19fa31-ddff-427f-9d73-f860de74bbc2}</Project>
<Name>Owin.Security.Providers.VisualStudio</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.VKontakte\Owin.Security.Providers.VKontakte.csproj">
<Project>{32d70e31-3799-482a-ac7a-081ff9206fc3}</Project>
<Name>Owin.Security.Providers.VKontakte</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Wargaming\Owin.Security.Providers.Wargaming.csproj">
<Project>{aa72bfce-8495-4a4d-988d-f8d490521776}</Project>
<Name>Owin.Security.Providers.Wargaming</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.WordPress\Owin.Security.Providers.WordPress.csproj">
<Project>{0ede8223-dd5f-4db8-a98a-64b1f4591f48}</Project>
<Name>Owin.Security.Providers.WordPress</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.WSO2\Owin.Security.Providers.WSO2.csproj">
<Project>{8fd3a9cb-e684-42c0-a8bf-7746fdd3d43c}</Project>
<Name>Owin.Security.Providers.WSO2</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Xing\Owin.Security.Providers.Xing.csproj">
<Project>{d497d8bd-6ef9-4c30-b195-b0dd153418d6}</Project>
<Name>Owin.Security.Providers.Xing</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Yahoo\Owin.Security.Providers.Yahoo.csproj">
<Project>{1765bedb-9e4b-468c-baf6-06784cdced67}</Project>
<Name>Owin.Security.Providers.Yahoo</Name>
</ProjectReference>
<ProjectReference Include="..\src\Owin.Security.Providers.Yammer\Owin.Security.Providers.Yammer.csproj">
<Project>{8d029a93-e687-4ddf-82b0-700ebbf477f7}</Project>
<Name>Owin.Security.Providers.Yammer</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>

View File

@@ -5,6 +5,7 @@
Provides a set of extra authentication providers for OWIN ([Project Katana](http://katanaproject.codeplex.com/)). This project includes providers for:
- OAuth
- ArcGISOnline
- ArcGISPortal
- Asana
- Backlog
- Battle.net
@@ -29,6 +30,7 @@ Provides a set of extra authentication providers for OWIN ([Project Katana](http
- Onshape
- ORCID
- PayPal
- Podbean
- Reddit
- Salesforce
- Shopify

View File

@@ -9,13 +9,13 @@ require 'nokogiri'
require 'openssl'
import 'nuget.rake'
CLEAN.include(['src/**/obj', 'src/**/bin', 'tool', 'packages/**','src/**/*.nuspec', 'src/**/*.nupkg', 'tools', 'packages', '*.nupkg'])
CLEAN.include(['src/**/obj', 'Owin.Security.Providers.nuspec', 'Owin.Security.Providers-signed.nuspec' 'src/**/bin', 'tool', 'packages/**','src/**/*.nuspec', 'src/**/*.nupkg', 'tools', 'packages', '*.nupkg'])
Configuration = ENV['CONFIGURATION'] || 'Release'
PACKAGES = File.expand_path("packages")
TOOLS = File.expand_path("tools")
NUGET = File.expand_path("#{TOOLS}/nuget")
NUGET_EXE = File.expand_path("#{TOOLS}/nuget/nuget.exe")
@version = "2.12.0"
@version = "2.23.0"
PROJECTS = Dir.glob('src/*').select{|dir| File.directory? dir }
desc 'Retrieve things'
@@ -31,12 +31,15 @@ task :preflight => [:clean, :build, :nuspec_gen]
desc 'publish'
task :publish => [:preflight,:nuspec_gen, :nuspec_pack, :nuspec_publish]
build :compile do |t|
t.prop 'Configuration', Configuration
t.sln = 'OwinOAuthProviders.sln'
t.prop 'SignAssembly', 'true'
t.prop 'AssemblyOriginatorKeyFile', File.expand_path("keypair.snk")
end
desc "Generate nuspec files"
task :nuspec_gen do
template = ERB.new(File.read('nuspectemplate.nuspec.erb'))
@@ -51,6 +54,7 @@ task :nuspec_gen do
File.write('Owin.Security.Providers.nuspec', ERB.new(File.read('global.nuspec.erb')).result())
end
desc 'pack nuspec files'
task :nuspec_pack do
PROJECTS.each{|dir|
@@ -61,12 +65,13 @@ task :nuspec_pack do
sh "#{NUGET_EXE} pack Owin.Security.Providers.nuspec -Exclude \"**\""
end
desc 'publish nugets'
task :nuspec_publish do
PROJECTS.each{|dir|
Dir.chdir(dir) do
sh "#{NUGET_EXE} push #{FileList["*.nupkg"].first}"
sh "#{NUGET_EXE} push -Source https://api.nuget.org/v3/index.json #{FileList["*.nupkg"].first}"
end
}
sh "#{NUGET_EXE} push #{FileList["*.nupkg"].first}"
sh "#{NUGET_EXE} push -Source https://api.nuget.org/v3/index.json #{FileList["*.nupkg"].first}"
end

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -89,6 +91,10 @@
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<PropertyGroup>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>..\..\keypair.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -2,7 +2,7 @@
<package >
<metadata>
<id>Owin.Security.Providers.OpenIDBase</id>
<version>2.1</version>
<version>2.1.1</version>
<authors>Jerrie Pelser, Tommy Parnell and contributors</authors>
<owners>Tommy Parnell</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>

BIN
keypair.snk Normal file

Binary file not shown.

View File

@@ -10,12 +10,12 @@ namespace :nuget do
begin
FileUtils.mkdir_p("#{NUGET}")
File.open("#{NUGET}/nuget.exe", "wb") do |file|
file.write open('http://nuget.org/nuget.exe', {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
file.write open('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
end
rescue
FileUtils.rm_rf("#{NUGET}/nuget.exe")
File.open("#{NUGET}/nuget.exe", "wb") do |file|
file.write open('https://dist.nuget.org/win-x86-commandline/v3.2.0/nuget.exe', {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
file.write open('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', {ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE}).read
end
end
end

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -0,0 +1,20 @@
using System;
namespace Owin.Security.Providers.ArcGISPortal
{
public static class ArcGISPortalAuthenticationExtensions
{
public static IAppBuilder UseArcGISPortalAuthentication(this IAppBuilder app,
ArcGISPortalAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException(nameof(options));
app.Use(typeof(ArcGISPortalAuthenticationMiddleware), app, options);
return app;
}
}
}

View File

@@ -0,0 +1,234 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
namespace Owin.Security.Providers.ArcGISPortal
{
public class ArcGISPortalAuthenticationHandler : AuthenticationHandler<ArcGISPortalAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
private readonly string _host;
public ArcGISPortalAuthenticationHandler(HttpClient httpClient, ILogger logger, string host)
{
_httpClient = httpClient;
_logger = logger;
_host = host;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
var query = Request.Query;
var values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
values = query.GetValues("state");
if (values != null && values.Count == 1)
{
state = values[0];
}
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, _logger))
{
return new AuthenticationTicket(null, properties);
}
var requestPrefix = Request.Scheme + "://" + Request.Host;
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("client_id", Options.ClientId),
new KeyValuePair<string, string>("client_secret", Options.ClientSecret)
};
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
var accessToken = (string)response.access_token;
var refreshToken = (string)response.refresh_token;
// Get the ArcGISPortal user
var userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?f=json&token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var userResponse = await _httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
var user = JsonConvert.DeserializeObject<Provider.ArcGISPortalUser>(text);
var context = new ArcGISPortalAuthenticatedContext(Context, user, accessToken, refreshToken, _host)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim("urn:ArcGISPortal:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:ArcGISPortal:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
_logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge == null) return Task.FromResult<object>(null);
var baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
var currentUri =
baseUri +
Request.Path +
Request.QueryString;
var redirectUri =
baseUri +
Options.CallbackPath;
var properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
GenerateCorrelationId(properties);
var state = Options.StateDataFormat.Protect(properties);
// comma separated
var scope = string.Join(",", Options.Scope);
var authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&response_type=" + Uri.EscapeDataString(scope) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (!Options.CallbackPath.HasValue || Options.CallbackPath != Request.Path) return false;
// TODO: error responses
var ticket = await AuthenticateAsync();
if (ticket == null)
{
_logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new ArcGISPortalReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
var grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
{
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
}
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (context.IsRequestCompleted || context.RedirectUri == null) return context.IsRequestCompleted;
var redirectUri = context.RedirectUri;
if (context.Identity == null)
{
// add a redirect hint that sign-in failed in some way
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
}
Response.Redirect(redirectUri);
context.RequestCompleted();
return context.IsRequestCompleted;
}
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Globalization;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
namespace Owin.Security.Providers.ArcGISPortal
{
public class ArcGISPortalAuthenticationMiddleware : AuthenticationMiddleware<ArcGISPortalAuthenticationOptions>
{
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public ArcGISPortalAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
ArcGISPortalAuthenticationOptions options)
: base(next, options)
{
if (string.IsNullOrWhiteSpace(Options.Host))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "Host"));
if (string.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientId"));
if (string.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientSecret"));
_logger = app.CreateLogger<ArcGISPortalAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new ArcGISPortalAuthenticationProvider();
if (Options.StateDataFormat == null)
{
var dataProtector = app.CreateDataProtector(
typeof(ArcGISPortalAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v2");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024 * 1024 * 10,
};
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin ArcGISPortal middleware");
_httpClient.DefaultRequestHeaders.ExpectContinue = false;
}
/// <summary>
/// Provides the <see cref="T:Microsoft.Owin.Security.Infrastructure.AuthenticationHandler" /> object for processing
/// authentication-related requests.
/// </summary>
/// <returns>
/// An <see cref="T:Microsoft.Owin.Security.Infrastructure.AuthenticationHandler" /> configured with the
/// <see cref="T:Owin.Security.Providers.ArcGISPortal.ArcGISPortalAuthenticationOptions" /> supplied to the constructor.
/// </returns>
protected override AuthenticationHandler<ArcGISPortalAuthenticationOptions> CreateHandler()
{
return new ArcGISPortalAuthenticationHandler(_httpClient, _logger, Options.Host);
}
private static HttpMessageHandler ResolveHttpMessageHandler(ArcGISPortalAuthenticationOptions options)
{
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}
}
}

View File

@@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security;
namespace Owin.Security.Providers.ArcGISPortal
{
public class ArcGISPortalAuthenticationOptions : AuthenticationOptions
{
public class ArcGISPortalAuthenticationEndpoints
{
/// <summary>
/// Endpoint which is used to redirect users to request ArcGISPortal access
/// </summary>
/// <remarks>
/// Defaults to https://www.arcgis.com/sharing/rest/oauth2/authorize/
/// </remarks>
public string AuthorizationEndpoint { get; set; }
/// <summary>
/// Endpoint which is used to exchange code for access token
/// </summary>
/// <remarks>
/// Defaults to https://www.arcgis.com/sharing/rest/oauth2/token/
/// </remarks>
public string TokenEndpoint { get; set; }
/// <summary>
/// Endpoint which is used to obtain user information after authentication
/// </summary>
/// <remarks>
/// Defaults to https://www.arcgis.com/sharing/rest/community/self
/// </remarks>
public string UserInfoEndpoint { get; set; }
}
private const string AuthenticationTypeNameDefault = "ArcGIS Portal";
private const string AuthorizationEndPoint = "arcgis/sharing/rest/oauth2/authorize/";
private const string TokenEndpoint = "arcgis/sharing/rest/oauth2/token/";
private const string UserInfoEndpoint = "arcgis/sharing/rest/community/self";
/// <summary>
/// Gets or sets the a pinned certificate validator to use to validate the endpoints used
/// in back channel communications belong to ArcGISPortal.
/// </summary>
/// <value>
/// The pinned certificate validator.
/// </value>
/// <remarks>
/// If this property is null then the default certificate checks are performed,
/// validating the subject name and if the signing chain is a trusted party.
/// </remarks>
public ICertificateValidator BackchannelCertificateValidator { get; set; }
/// <summary>
/// The HttpMessageHandler used to communicate with ArcGISPortal.
/// This cannot be set at the same time as BackchannelCertificateValidator unless the value
/// can be downcast to a WebRequestHandler.
/// </summary>
public HttpMessageHandler BackchannelHttpHandler { get; set; }
/// <summary>
/// Gets or sets timeout value in milliseconds for back channel communications with ArcGISPortal.
/// </summary>
/// <value>
/// The back channel timeout in milliseconds.
/// </value>
public TimeSpan BackchannelTimeout { get; set; }
/// <summary>
/// The request path within the application's base path where the user-agent will be returned.
/// The middleware will process this request when it arrives.
/// Default value is "/signin-ArcGISPortal".
/// </summary>
public PathString CallbackPath { get; set; }
/// <summary>
/// Get or sets the text that the user can display on a sign in user interface.
/// </summary>
public string Caption
{
get { return Description.Caption; }
set { Description.Caption = value; }
}
/// <summary>
/// Gets or sets the ArcGIS Portal Authentication Type Name
/// Displayed to the user as the login option, and allows multiple ArcGIS Portal OAuth providers to be configured for use in the same application.
/// </summary>
public string AuthenticationTypeName { get; set; }
/// <summary>
/// Gets or sets the ArcGIS Portal Host (where the portal is installed e.g. https://arcgisportal.domain.com)
/// </summary>
public string Host { get; set; }
/// <summary>
/// Gets or sets the ArcGISPortal supplied Client ID
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// Gets or sets the ArcGISPortal supplied Client Secret
/// </summary>
public string ClientSecret { get; set; }
/// <summary>
/// Gets the sets of OAuth endpoints used to authenticate against ArcGISPortal. Overriding these endpoints allows you to use ArcGISPortal Enterprise for
/// authentication.
/// </summary>
public ArcGISPortalAuthenticationEndpoints Endpoints { get; set; }
/// <summary>
/// Gets or sets the <see cref="IArcGISPortalAuthenticationProvider" /> used in the authentication events
/// </summary>
public IArcGISPortalAuthenticationProvider Provider { get; set; }
/// <summary>
/// A list of permissions to request.
/// </summary>
public IList<string> Scope { get; protected set; }
/// <summary>
/// Gets or sets the name of another authentication middleware which will be responsible for actually issuing a user
/// <see cref="System.Security.Claims.ClaimsIdentity" />.
/// </summary>
public string SignInAsAuthenticationType { get; set; }
/// <summary>
/// Gets or sets the type used to secure data handled by the middleware.
/// </summary>
public ISecureDataFormat<AuthenticationProperties> StateDataFormat { get; set; }
/// <summary>
/// Initializes a new <see cref="ArcGISPortalAuthenticationOptions" />
/// </summary>
public ArcGISPortalAuthenticationOptions(string host, string clientId, string clientSecret) : this(AuthenticationTypeNameDefault, host, clientId, clientSecret) {}
/// <summary>
/// Initializes a new <see cref="ArcGISPortalAuthenticationOptions" />
/// </summary>
public ArcGISPortalAuthenticationOptions(string authenticationTypeName, string host, string clientId, string clientSecret) : base(authenticationTypeName)
{
AuthenticationTypeName = authenticationTypeName;
Host = host;
ClientId = clientId;
ClientSecret = clientSecret;
AuthenticationType = AuthenticationTypeName;
Caption = AuthenticationTypeName;
CallbackPath = new PathString("/signin-arcgis-portal");
AuthenticationMode = AuthenticationMode.Passive;
Scope = new List<string>
{
"code"
};
BackchannelTimeout = TimeSpan.FromSeconds(60);
Uri hostUri = new Uri(Host);
Endpoints = new ArcGISPortalAuthenticationEndpoints
{
AuthorizationEndpoint = new Uri(hostUri, AuthorizationEndPoint).ToString(),
TokenEndpoint = new Uri(hostUri, TokenEndpoint).ToString(),
UserInfoEndpoint = new Uri(hostUri, UserInfoEndpoint).ToString()
};
}
}
}

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{18547CA4-D7D3-43C2-81C2-A21FC8151A93}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.ArcGISPortal</RootNamespace>
<AssemblyName>Owin.Security.Providers.ArcGISPortal</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArcGISPortalAuthenticationHandler.cs" />
<Compile Include="ArcGISPortalAuthenticationExtensions.cs" />
<Compile Include="ArcGISPortalAuthenticationMiddleware.cs" />
<Compile Include="ArcGISPortalAuthenticationOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Provider\ArcGISPortalAuthenticationProvider.cs" />
<Compile Include="Provider\ArcGISPortalAuthenticatedContext.cs" />
<Compile Include="Provider\ArcGISPortalReturnEndpointContext.cs" />
<Compile Include="Provider\ArcGISPortalUser.cs" />
<Compile Include="Provider\IArcGISPortalAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Owin.Security.Providers.ArcGISPortal")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.ArcGISPortal")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("18547ca4-d7d3-43c2-81c2-a21fc8151a93")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,81 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System.Security.Claims;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
using Owin.Security.Providers.ArcGISPortal.Provider;
using System;
namespace Owin.Security.Providers.ArcGISPortal
{
/// <summary>
/// Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.
/// </summary>
public class ArcGISPortalAuthenticatedContext : BaseContext
{
/// <summary>
/// Initializes a <see cref="ArcGISPortalAuthenticatedContext"/>
/// </summary>
/// <param name="context">The OWIN environment</param>
/// <param name="user">The ArcGIS Portal user</param>
/// <param name="accessToken">ArcGIS Portal Access token</param>
/// <param name="refreshToken">ArcGIS Portal Refresh token</param>
/// <param name="host">ArcGIS Portal Host</param>
public ArcGISPortalAuthenticatedContext(IOwinContext context, ArcGISPortalUser user, string accessToken, string refreshToken, string host)
: base(context)
{
Uri hostUri = new Uri(host);
AccessToken = accessToken;
RefreshToken = refreshToken;
Id = user.Username;
Name = user.FullName;
Link = new Uri(hostUri, "arcgis/sharing/rest/community/users/" + Id).ToString();
UserName = Id;
Email = user.Email;
}
/// <summary>
/// Gets the ArcGIS Portal access token
/// </summary>
public string AccessToken { get; private set; }
/// <summary>
/// Gets the ArcGIS Portal refresh token
/// </summary>
public string RefreshToken { get; private set; }
/// <summary>
/// Gets the ArcGIS Portal user ID
/// </summary>
public string Id { get; }
/// <summary>
/// Gets the user's name
/// </summary>
public string Name { get; private set; }
/// <summary>
/// Gets the user's email
/// </summary>
public string Email { get; private set; }
public string Link { get; private set; }
/// <summary>
/// Gets the ArcGIS Portal username
/// </summary>
public string UserName { get; private set; }
/// <summary>
/// Gets the <see cref="ClaimsIdentity"/> representing the user
/// </summary>
public ClaimsIdentity Identity { get; set; }
/// <summary>
/// Gets or sets a property bag for common authentication properties
/// </summary>
public AuthenticationProperties Properties { get; set; }
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Threading.Tasks;
namespace Owin.Security.Providers.ArcGISPortal
{
/// <summary>
/// Default <see cref="IArcGISPortalAuthenticationProvider"/> implementation.
/// </summary>
public class ArcGISPortalAuthenticationProvider : IArcGISPortalAuthenticationProvider
{
/// <summary>
/// Initializes a <see cref="ArcGISPortalAuthenticationProvider"/>
/// </summary>
public ArcGISPortalAuthenticationProvider()
{
OnAuthenticated = context => Task.FromResult<object>(null);
OnReturnEndpoint = context => Task.FromResult<object>(null);
}
/// <summary>
/// Gets or sets the function that is invoked when the Authenticated method is invoked.
/// </summary>
public Func<ArcGISPortalAuthenticatedContext, Task> OnAuthenticated { get; set; }
/// <summary>
/// Gets or sets the function that is invoked when the ReturnEndpoint method is invoked.
/// </summary>
public Func<ArcGISPortalReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever ArcGISPortal successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
public virtual Task Authenticated(ArcGISPortalAuthenticatedContext context)
{
return OnAuthenticated(context);
}
/// <summary>
/// Invoked prior to the <see cref="System.Security.Claims.ClaimsIdentity"/> being saved in a local cookie and the browser being redirected to the originally requested URL.
/// </summary>
/// <param name="context"></param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
public virtual Task ReturnEndpoint(ArcGISPortalReturnEndpointContext context)
{
return OnReturnEndpoint(context);
}
}
}

View File

@@ -0,0 +1,26 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
namespace Owin.Security.Providers.ArcGISPortal
{
/// <summary>
/// Provides context information to middleware providers.
/// </summary>
public class ArcGISPortalReturnEndpointContext : ReturnEndpointContext
{
/// <summary>
///
/// </summary>
/// <param name="context">OWIN environment</param>
/// <param name="ticket">The authentication ticket</param>
public ArcGISPortalReturnEndpointContext(
IOwinContext context,
AuthenticationTicket ticket)
: base(context, ticket)
{
}
}
}

View File

@@ -0,0 +1,9 @@
namespace Owin.Security.Providers.ArcGISPortal.Provider
{
public class ArcGISPortalUser
{
public string Username { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
using System.Threading.Tasks;
namespace Owin.Security.Providers.ArcGISPortal
{
/// <summary>
/// Specifies callback methods which the <see cref="ArcGISPortalAuthenticationMiddleware"></see> invokes to enable developer control over the authentication process. />
/// </summary>
public interface IArcGISPortalAuthenticationProvider
{
/// <summary>
/// Invoked whenever ArcGISPortal successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
Task Authenticated(ArcGISPortalAuthenticatedContext context);
/// <summary>
/// Invoked prior to the <see cref="System.Security.Claims.ClaimsIdentity"/> being saved in a local cookie and the browser being redirected to the originally requested URL.
/// </summary>
/// <param name="context"></param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
Task ReturnEndpoint(ArcGISPortalReturnEndpointContext context);
}
}

View File

@@ -0,0 +1,81 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Owin.Security.Providers.ArcGISPortal {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.ArcGISPortal.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; option must be provided..
/// </summary>
internal static string Exception_OptionMustBeProvided {
get {
return ResourceManager.GetString("Exception_OptionMustBeProvided", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An ICertificateValidator cannot be specified at the same time as an HttpMessageHandler unless it is a WebRequestHandler..
/// </summary>
internal static string Exception_ValidatorHandlerMismatch {
get {
return ResourceManager.GetString("Exception_ValidatorHandlerMismatch", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Exception_OptionMustBeProvided" xml:space="preserve">
<value>The '{0}' option must be provided.</value>
</data>
<data name="Exception_ValidatorHandlerMismatch" xml:space="preserve">
<value>An ICertificateValidator cannot be specified at the same time as an HttpMessageHandler unless it is a WebRequestHandler.</value>
</data>
</root>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
</packages>

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -105,7 +105,7 @@ namespace Owin.Security.Providers.Discord
};
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.UserName, XmlSchemaString, Options.AuthenticationType));
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -17,8 +17,9 @@ namespace Owin.Security.Providers.Dropbox
{
private const string StateCookie = "_DropboxState";
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.dropbox.com/1/oauth2/token";
private const string UserInfoEndpoint = "https://api.dropbox.com/1/account/info";
private const string TokenEndpoint = "https://api.dropbox.com/oauth2/token";
private const string UserInfoEndpoint = "https://api.dropbox.com/2/users/get_current_account";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
@@ -65,13 +66,13 @@ namespace Owin.Security.Providers.Dropbox
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>
var body = new Dictionary<string, string>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("client_id", Options.AppKey),
new KeyValuePair<string, string>("client_secret", Options.AppSecret)
{ "grant_type", "authorization_code" },
{ "code", code },
{"redirect_uri", redirectUri },
{ "client_id", Options.AppKey },
{ "client_secret", Options.AppSecret }
};
// Request the token
@@ -85,8 +86,8 @@ namespace Owin.Security.Providers.Dropbox
var accessToken = (string)response.access_token;
// Get the Dropbox user
var graphResponse = await _httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var graphResponse = await _httpClient.PostAsync(UserInfoEndpoint, null);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
var user = JObject.Parse(text);
@@ -154,7 +155,7 @@ namespace Owin.Security.Providers.Dropbox
GenerateCorrelationId(properties);
var authorizationEndpoint =
"https://www.dropbox.com/1/oauth2/authorize" +
"https://www.dropbox.com/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.AppKey) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri);

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -25,7 +25,7 @@ namespace Owin.Security.Providers.Dropbox
AccessToken = accessToken;
User = user;
Id = TryGetValue(user, "uid");
Id = TryGetValue(user, "account_id");
Name = TryGetValue(user, "display_name");
}

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -29,6 +30,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Accessibility" />

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -16,7 +16,7 @@ namespace Owin.Security.Providers.LinkedIn
public class LinkedInAuthenticationHandler : AuthenticationHandler<LinkedInAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://www.linkedin.com/uas/oauth2/accessToken";
private const string TokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
private const string UserInfoEndpoint = "https://api.linkedin.com/v1/people/";
private readonly ILogger _logger;
@@ -61,7 +61,7 @@ namespace Owin.Security.Providers.LinkedIn
return new AuthenticationTicket(null, properties);
}
var requestPrefix = Request.Scheme + "://" + Request.Host;
var requestPrefix = Request.Scheme + "://" + this.GetHostName();
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
@@ -173,7 +173,7 @@ namespace Owin.Security.Providers.LinkedIn
var baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
this.GetHostName() +
Request.PathBase;
var currentUri =
@@ -206,7 +206,7 @@ namespace Owin.Security.Providers.LinkedIn
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
"https://www.linkedin.com/uas/oauth2/authorization" +
"https://www.linkedin.com/oauth/v2/authorization" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
@@ -271,5 +271,15 @@ namespace Owin.Security.Providers.LinkedIn
return context.IsRequestCompleted;
}
/// <summary>
/// Gets proxy host name from <see cref="LinkedInAuthenticationOptions"/> if it is set.
/// If proxy host name is not set, gets application request host name.
/// </summary>
/// <returns>Host name.</returns>
private string GetHostName()
{
return string.IsNullOrWhiteSpace(Options.ProxyHost) ? Request.Host.ToString() : Options.ProxyHost;
}
}
}

View File

@@ -43,6 +43,16 @@ namespace Owin.Security.Providers.LinkedIn
/// </summary>
public PathString CallbackPath { get; set; }
/// <summary>
/// Gets or sets the middleware host name.
/// The middleware processes the <see cref="CallbackPath"/> on this host name instead of the application's request host.
/// If this is not set, the application's request host will be used.
/// </summary>
/// <remarks>
/// Use this property when running behind a proxy.
/// </remarks>
public string ProxyHost { get; set; }
/// <summary>
/// Get or sets the text that the user can display on a sign in user interface.
/// </summary>

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -21,6 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -29,6 +30,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -46,9 +48,8 @@
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin.Security.Providers.OpenIDBase, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.Security.Providers.OpenIDBase.2.1\lib\net45\Owin.Security.Providers.OpenIDBase.dll</HintPath>
<Private>True</Private>
<Reference Include="Owin.Security.Providers.OpenIDBase, Version=2.0.0.0, Culture=neutral, PublicKeyToken=1328b8c16b108c43, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.Security.Providers.OpenIDBase.2.1.1\lib\net45\Owin.Security.Providers.OpenIDBase.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@@ -4,5 +4,5 @@
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Owin.Security.Providers.OpenIDBase" version="2.1" targetFramework="net45" />
<package id="Owin.Security.Providers.OpenIDBase" version="2.1.1" targetFramework="net45" />
</packages>

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -81,9 +81,25 @@ namespace Owin.Security.Providers.PayPal
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
});
string text = "";
try
{
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
text = await tokenResponse.Content.ReadAsStringAsync();
}
catch (HttpRequestException ex)
{
if (ex.InnerException is System.Net.WebException && ex.InnerException.Message.Contains("TLS"))
{
if (!System.Net.ServicePointManager.SecurityProtocol.HasFlag(System.Net.SecurityProtocolType.Tls12))
{
throw new System.Net.WebException("PayPal requires TLS v1.2. TLS v1.0 and v1.1 connections will be refused. Set System.Net.ServicePointManager.SecurityProtocol = System.Net.ServicePointManager.SecurityProtocol | System.Net.SecurityProtocolType.Tls12", ex.InnerException);
}
}
throw;
}
// Deserializes the token response
var response = JsonConvert.DeserializeObject<dynamic>(text);

View File

@@ -0,0 +1,7 @@
namespace Owin.Security.Providers.Podbean
{
internal static class Constants
{
public const string DefaultAuthenticationType = "Podbean";
}
}

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A7B95FD4-08AD-499F-B574-07560CC2A63F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.Podbean</RootNamespace>
<AssemblyName>Owin.Security.Providers.Podbean</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="PodbeanAuthenticationExtensions.cs" />
<Compile Include="PodbeanAuthenticationHandler.cs" />
<Compile Include="PodbeanAuthenticationMiddleware.cs" />
<Compile Include="PodbeanAuthenticationOptions.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Provider\PodbeanAuthenticatedContext.cs" />
<Compile Include="Provider\PodbeanAuthenticationProvider.cs" />
<Compile Include="Provider\PodbeanReturnEndpointContext.cs" />
<Compile Include="Provider\IPodbeanAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<ItemGroup>
<VersionNumber Include="@(Targets->'%(Version)')" />
</ItemGroup>
</Target>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,33 @@
#region
using System;
#endregion
namespace Owin.Security.Providers.Podbean
{
public static class PodbeanAuthenticationExtensions
{
public static IAppBuilder UsePodbeanAuthentication(this IAppBuilder app,
PodbeanAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException(nameof(options));
app.Use(typeof(PodbeanAuthenticationMiddleware), app, options);
return app;
}
public static IAppBuilder UsePodbeanAuthentication(this IAppBuilder app, string appId, string appSecret)
{
return app.UsePodbeanAuthentication(new PodbeanAuthenticationOptions
{
AppId = appId,
AppSecret = appSecret
});
}
}
}

View File

@@ -0,0 +1,246 @@
#region
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Microsoft.Owin;
using System.Net.Http.Headers;
#endregion
namespace Owin.Security.Providers.Podbean
{
public class PodbeanAuthenticationHandler : AuthenticationHandler<PodbeanAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.podbean.com/v1/oauth/token";
private const string PodcastIdEndpoint = "https://api.podbean.com/v1/oauth/debugToken";
private const string PodcastEndpoint = "https://api.podbean.com/v1/podcast";
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public PodbeanAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
var query = Request.Query;
var values = query.GetValues("code");
if (values != null && values.Count == 1)
code = values[0];
values = query.GetValues("state");
if (values != null && values.Count == 1)
state = values[0];
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
return null;
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, _logger))
return new AuthenticationTicket(null, properties);
var requestPrefix = GetBaseUri(Request);
var redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri)
};
// Request the token
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, TokenEndpoint);
tokenRequest.Headers.Authorization =
new AuthenticationHeaderValue("Basic", Base64Encode($"{Options.AppId}:{Options.AppSecret}"));
tokenRequest.Content = new FormUrlEncodedContent(body);
var tokenResponse = await _httpClient.SendAsync(tokenRequest, Request.CallCancelled);
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic token = JsonConvert.DeserializeObject<dynamic>(text);
var accessToken = (string)token.access_token;
var refreshToken = (string)token.refresh_token;
var expires = (string)token.expires_in;
// Get the Podbean podcast
var podcastResponse = await _httpClient.GetAsync(
$"{PodcastEndpoint}?access_token={Uri.EscapeDataString(accessToken)}", Request.CallCancelled);
podcastResponse.EnsureSuccessStatusCode();
text = await podcastResponse.Content.ReadAsStringAsync();
var podcast = JObject.Parse(text)["podcast"].ToObject<Podcast>();
// Get the Podbean podcast id
var podcastIdRequest = new HttpRequestMessage(HttpMethod.Get, $"{PodcastIdEndpoint}?access_token={Uri.EscapeDataString(accessToken)}");
podcastIdRequest.Headers.Authorization =
new AuthenticationHeaderValue("Basic", Base64Encode($"{Options.AppId}:{Options.AppSecret}"));
var podcastIdResponse = await _httpClient.SendAsync(podcastIdRequest, Request.CallCancelled);
podcastIdResponse.EnsureSuccessStatusCode();
text = await podcastIdResponse.Content.ReadAsStringAsync();
var podcastId = JsonConvert.DeserializeObject<dynamic>(text);
podcast.Id = (string)podcastId.podcast_id;
var context = new PodbeanAuthenticatedContext(Context, podcast, accessToken, refreshToken, expires)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
if (!string.IsNullOrEmpty(context.Id))
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id, XmlSchemaString,
Options.AuthenticationType));
if (!string.IsNullOrEmpty(context.Name))
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.Name,
XmlSchemaString, Options.AuthenticationType));
context.Properties = properties;
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
_logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
return Task.FromResult<object>(null);
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge == null) return Task.FromResult<object>(null);
var baseUri = GetBaseUri(Request);
var currentUri =
baseUri +
Request.Path +
Request.QueryString;
var redirectUri =
baseUri +
Options.CallbackPath;
var properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
properties.RedirectUri = currentUri;
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
var state = Options.StateDataFormat.Protect(properties);
var scope = string.Join(" ", Options.Scope);
var authorizationEndpoint =
"https://api.podbean.com/v1/dialog/oauth" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.AppId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state);
Response.Redirect(authorizationEndpoint);
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
private async Task<bool> InvokeReplyPathAsync()
{
if (!Options.CallbackPath.HasValue || Options.CallbackPath != Request.Path) return false;
// TODO: error responses
var ticket = await AuthenticateAsync();
if (ticket == null)
{
_logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new PodbeanReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
var grantIdentity = context.Identity;
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType,
StringComparison.Ordinal))
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType,
grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
Context.Authentication.SignIn(context.Properties, grantIdentity);
}
if (context.IsRequestCompleted || context.RedirectUri == null) return context.IsRequestCompleted;
var redirectUri = context.RedirectUri;
if (context.Identity == null)
redirectUri = WebUtilities.AddQueryString(redirectUri, "error", "access_denied");
Response.Redirect(redirectUri);
context.RequestCompleted();
return context.IsRequestCompleted;
}
private static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
private string GetBaseUri(IOwinRequest request)
{
if (Options.DebugUsingRequestHeadersToBuildBaseUri &&
request.Headers["X-Original-Host"] != null &&
request.Headers["X-Forwarded-Proto"] != null)
{
return request.Headers["X-Forwarded-Proto"] + Uri.SchemeDelimiter + request.Headers["X-Original-Host"];
}
var baseUri =
request.Scheme +
Uri.SchemeDelimiter +
request.Host +
request.PathBase;
return baseUri;
}
}
}

View File

@@ -0,0 +1,84 @@
#region
using System;
using System.Globalization;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
#endregion
namespace Owin.Security.Providers.Podbean
{
public class PodbeanAuthenticationMiddleware : AuthenticationMiddleware<PodbeanAuthenticationOptions>
{
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public PodbeanAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
PodbeanAuthenticationOptions options)
: base(next, options)
{
if (string.IsNullOrWhiteSpace(Options.AppId))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "AppId"));
if (string.IsNullOrWhiteSpace(Options.AppSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "AppSecret"));
_logger = app.CreateLogger<PodbeanAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new PodbeanAuthenticationProvider();
if (Options.StateDataFormat == null)
{
var dataProtector = app.CreateDataProtector(
typeof(PodbeanAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024 * 1024 * 10
};
}
/// <summary>
/// Provides the <see cref="T:Microsoft.Owin.Security.Infrastructure.AuthenticationHandler" /> object for processing
/// authentication-related requests.
/// </summary>
/// <returns>
/// An <see cref="T:Microsoft.Owin.Security.Infrastructure.AuthenticationHandler" /> configured with the
/// <see cref="T:Owin.Security.Providers.Podbean.PodbeanAuthenticationOptions" /> supplied to the constructor.
/// </returns>
protected override AuthenticationHandler<PodbeanAuthenticationOptions> CreateHandler()
{
return new PodbeanAuthenticationHandler(_httpClient, _logger);
}
private static HttpMessageHandler ResolveHttpMessageHandler(PodbeanAuthenticationOptions options)
{
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}
}
}

View File

@@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security;
namespace Owin.Security.Providers.Podbean
{
public class PodbeanAuthenticationOptions : AuthenticationOptions
{
/// <summary>
/// Initializes a new <see cref="PodbeanAuthenticationOptions" />
/// </summary>
public PodbeanAuthenticationOptions()
: base("Podbean")
{
Caption = Constants.DefaultAuthenticationType;
CallbackPath = new PathString("/signin-podbean");
AuthenticationMode = AuthenticationMode.Passive;
Scope = new List<string>
{
"podcast_read"
};
BackchannelTimeout = TimeSpan.FromSeconds(60);
}
/// <summary>
/// Gets or sets the a pinned certificate validator to use to validate the endpoints used
/// in back channel communications belong to Podbean
/// </summary>
/// <value>
/// The pinned certificate validator.
/// </value>
/// <remarks>
/// If this property is null then the default certificate checks are performed,
/// validating the subject name and if the signing chain is a trusted party.
/// </remarks>
public ICertificateValidator BackchannelCertificateValidator { get; set; }
/// <summary>
/// The HttpMessageHandler used to communicate with Podbean.
/// This cannot be set at the same time as BackchannelCertificateValidator unless the value
/// can be downcast to a WebRequestHandler.
/// </summary>
public HttpMessageHandler BackchannelHttpHandler { get; set; }
/// <summary>
/// Gets or sets timeout value in milliseconds for back channel communications with Podbean.
/// </summary>
/// <value>
/// The back channel timeout in milliseconds.
/// </value>
public TimeSpan BackchannelTimeout { get; set; }
/// <summary>
/// The request path within the application's base path where the user-agent will be returned.
/// The middleware will process this request when it arrives.
/// Default value is "/signin-Podbean".
/// </summary>
public PathString CallbackPath { get; set; }
/// <summary>
/// Get or sets the text that the user can display on a sign in user interface.
/// </summary>
public string Caption
{
get { return Description.Caption; }
set { Description.Caption = value; }
}
/// <summary>
/// Gets or sets the Podbean supplied App ID
/// </summary>
public string AppId { get; set; }
/// <summary>
/// Gets or sets the Podbean supplied App Secret
/// </summary>
public string AppSecret { get; set; }
/// <summary>
/// Set this value to true to debug locally using a service such as https://ngrok.io.
/// Podbean doesn't allow you to redirect to localhost. Ngrok and similar services
/// set the X-Original-Host and X-Forwarded-Proto headers to build the base Uri for
/// redirects back to localhost.
/// </summary>
public bool DebugUsingRequestHeadersToBuildBaseUri { get; set; }
/// <summary>
/// A list of permissions to request.
/// </summary>
public IList<string> Scope { get; private set; }
/// <summary>
/// Gets or sets the <see cref="IPodbeanAuthenticationProvider" /> used in the authentication events
/// </summary>
public IPodbeanAuthenticationProvider Provider { get; set; }
/// <summary>
/// Gets or sets the name of another authentication middleware which will be responsible for actually issuing a user
/// <see cref="System.Security.Claims.ClaimsIdentity" />.
/// </summary>
public string SignInAsAuthenticationType { get; set; }
/// <summary>
/// Gets or sets the type used to secure data handled by the middleware.
/// </summary>
public ISecureDataFormat<AuthenticationProperties> StateDataFormat { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.Podbean")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.Podbean")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("38815307-3360-4f54-9204-03fae50160bc")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -0,0 +1,33 @@
#region
using System.Threading.Tasks;
#endregion
namespace Owin.Security.Providers.Podbean
{
/// <summary>
/// Specifies callback methods which the <see cref="PodbeanAuthenticationMiddleware"></see> invokes to enable developer
/// control over the authentication process. />
/// </summary>
public interface IPodbeanAuthenticationProvider
{
/// <summary>
/// Invoked whenever Podbean successfully authenticates a user
/// </summary>
/// <param name="context">
/// Contains information about the login session as well as the user
/// <see cref="System.Security.Claims.ClaimsIdentity" />.
/// </param>
/// <returns>A <see cref="Task" /> representing the completed operation.</returns>
Task Authenticated(PodbeanAuthenticatedContext context);
/// <summary>
/// Invoked prior to the <see cref="System.Security.Claims.ClaimsIdentity" /> being saved in a local cookie and the
/// browser being redirected to the originally requested URL.
/// </summary>
/// <param name="context"></param>
/// <returns>A <see cref="Task" /> representing the completed operation.</returns>
Task ReturnEndpoint(PodbeanReturnEndpointContext context);
}
}

View File

@@ -0,0 +1,130 @@
#region
using System;
using System.Globalization;
using System.Security.Claims;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
#endregion
namespace Owin.Security.Providers.Podbean
{
/// <summary>
/// Contains information about the login session as well as the user
/// <see cref="System.Security.Claims.ClaimsIdentity" />.
/// </summary>
public class PodbeanAuthenticatedContext : BaseContext
{
/// <summary>
/// Initializes a <see cref="PodbeanAuthenticatedContext" />
/// </summary>
/// <param name="context">The OWIN environment</param>
/// <param name="podcast">The <see cref="Podcast"/></param>
/// <param name="accessToken">Podbean Access token</param>
/// <param name="refreshToken">Podbean Refresh token</param>
/// <param name="expires">Seconds until expiration</param>
public PodbeanAuthenticatedContext(IOwinContext context, Podcast podcast, string accessToken, string refreshToken, string expires)
: base(context)
{
Podcast = podcast;
Id = podcast.Id;
Name = podcast.Title;
AccessToken = accessToken;
RefreshToken = refreshToken;
int expiresValue;
if (int.TryParse(expires, NumberStyles.Integer, CultureInfo.InvariantCulture, out expiresValue))
ExpiresIn = TimeSpan.FromSeconds(expiresValue);
}
/// <summary>
/// Gets the JSON-serialized user
/// </summary>
/// <remarks>
/// Contains the Podbean user obtained from the endpoint https://api.Podbeanapp.com/1/user.json
/// </remarks>
public Podcast Podcast { get; }
/// <summary>
/// Gets the Podbean OAuth access token
/// </summary>
public string AccessToken { get; }
/// <summary>
/// Gets the Podbean OAuth refresh token
/// </summary>
public string RefreshToken { get; }
/// <summary>
/// Gets the Podbean access token expiration time
/// </summary>
public TimeSpan? ExpiresIn { get; set; }
/// <summary>
/// Gets the Podbean Podcast ID
/// </summary>
public string Id { get; }
/// <summary>
/// The name of the user
/// </summary>
public string Name { get; }
/// <summary>
/// Gets the <see cref="ClaimsIdentity" /> representing the user
/// </summary>
public ClaimsIdentity Identity { get; set; }
/// <summary>
/// Gets or sets a property bag for common authentication properties
/// </summary>
public AuthenticationProperties Properties { get; set; }
}
public class Podcast
{
/// <summary>
/// The Id of the <see cref="Podcast"/>
/// </summary>
public string Id { get; set; }
/// <summary>
/// The title of the <see cref="Podcast"/>
/// </summary>
public string Title { get; set; }
/// <summary>
/// The description of the <see cref="Podcast"/>
/// </summary>
[JsonProperty(PropertyName = "desc")]
public string Description { get; set; }
/// <summary>
/// A url to an image representing the logo of the <see cref="Podcast"/>
/// </summary>
public string Logo { get; set; }
/// <summary>
/// A url to the <see cref="Podcast"/>'s website
/// </summary>
public string Website { get; set; }
/// <summary>
/// The name of the category of the <see cref="Podcast"/>
/// </summary>
[JsonProperty(PropertyName = "category_name")]
public string CategoryName { get; set; }
/// <summary>
/// The episode types of the <see cref="Podcast"/>.
/// The possible value is a combination of public, premium or private
/// </summary>
[JsonProperty(PropertyName = "allow_episode_type")]
public string[] AllowEpisodeTypes { get; set; }
}
}

View File

@@ -0,0 +1,58 @@
#region
using System;
using System.Threading.Tasks;
#endregion
namespace Owin.Security.Providers.Podbean
{
/// <summary>
/// Default <see cref="IPodbeanAuthenticationProvider" /> implementation.
/// </summary>
public class PodbeanAuthenticationProvider : IPodbeanAuthenticationProvider
{
/// <summary>
/// Initializes a <see cref="PodbeanAuthenticationProvider" />
/// </summary>
public PodbeanAuthenticationProvider()
{
OnAuthenticated = context => Task.FromResult<object>(null);
OnReturnEndpoint = context => Task.FromResult<object>(null);
}
/// <summary>
/// Gets or sets the function that is invoked when the Authenticated method is invoked.
/// </summary>
public Func<PodbeanAuthenticatedContext, Task> OnAuthenticated { get; set; }
/// <summary>
/// Gets or sets the function that is invoked when the ReturnEndpoint method is invoked.
/// </summary>
public Func<PodbeanReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever Podbean successfully authenticates a user
/// </summary>
/// <param name="context">
/// Contains information about the login session as well as the user
/// <see cref="System.Security.Claims.ClaimsIdentity" />.
/// </param>
/// <returns>A <see cref="Task" /> representing the completed operation.</returns>
public virtual Task Authenticated(PodbeanAuthenticatedContext context)
{
return OnAuthenticated(context);
}
/// <summary>
/// Invoked prior to the <see cref="System.Security.Claims.ClaimsIdentity" /> being saved in a local cookie and the
/// browser being redirected to the originally requested URL.
/// </summary>
/// <param name="context"></param>
/// <returns>A <see cref="Task" /> representing the completed operation.</returns>
public virtual Task ReturnEndpoint(PodbeanReturnEndpointContext context)
{
return OnReturnEndpoint(context);
}
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
namespace Owin.Security.Providers.Podbean
{
/// <summary>
/// Provides context information to middleware providers.
/// </summary>
public class PodbeanReturnEndpointContext : ReturnEndpointContext
{
/// <summary>
/// </summary>
/// <param name="context">OWIN environment</param>
/// <param name="ticket">The authentication ticket</param>
public PodbeanReturnEndpointContext(
IOwinContext context,
AuthenticationTicket ticket)
: base(context, ticket)
{
}
}
}

View File

@@ -0,0 +1,81 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Owin.Security.Providers.Podbean {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.Podbean.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The &apos;{0}&apos; option must be provided..
/// </summary>
internal static string Exception_OptionMustBeProvided {
get {
return ResourceManager.GetString("Exception_OptionMustBeProvided", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to An ICertificateValidator cannot be specified at the same time as an HttpMessageHandler unless it is a WebRequestHandler..
/// </summary>
internal static string Exception_ValidatorHandlerMismatch {
get {
return ResourceManager.GetString("Exception_ValidatorHandlerMismatch", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Exception_OptionMustBeProvided" xml:space="preserve">
<value>The '{0}' option must be provided.</value>
</data>
<data name="Exception_ValidatorHandlerMismatch" xml:space="preserve">
<value>An ICertificateValidator cannot be specified at the same time as an HttpMessageHandler unless it is a WebRequestHandler.</value>
</data>
</root>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
</packages>

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -1,7 +1,11 @@
namespace Owin.Security.Providers.Salesforce
{
internal static class Constants
public static class Constants
{
public const string DefaultAuthenticationType = "Salesforce";
public const string EnvironmentAuthenticationProperty = "Environment";
public const string ProductionEnvironment = "Production";
public const string SandboxEnvironment = "Sandbox";
}
}

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -18,6 +18,12 @@ namespace Owin.Security.Providers.Salesforce
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string ProductionHost = "https://login.salesforce.com";
private const string SandboxHost = "https://test.salesforce.com";
private const string AuthorizationEndpoint = "/services/oauth2/authorize";
private const string TokenEndpoint = "/services/oauth2/token";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
@@ -74,7 +80,7 @@ namespace Owin.Security.Providers.Salesforce
};
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
var requestMessage = new HttpRequestMessage(HttpMethod.Post, ComposeTokenEndpoint(properties));
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
var tokenResponse = await _httpClient.SendAsync(requestMessage);
@@ -186,8 +192,10 @@ namespace Owin.Security.Providers.Salesforce
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
$"{Options.Endpoints.AuthorizationEndpoint}?response_type={"code"}&client_id={Options.ClientId}&redirect_uri={HttpUtility.UrlEncode(redirectUri)}&display={"page"}&immediate={false}&state={Uri.EscapeDataString(state)}";
var authorizationEndpoint = ComposeAuthorizationEndpoint(properties);
authorizationEndpoint =
$"{authorizationEndpoint}?response_type={"code"}&client_id={Options.ClientId}&redirect_uri={HttpUtility.UrlEncode(redirectUri)}&display={"page"}&immediate={false}&state={Uri.EscapeDataString(state)}";
if (Options.Scope != null && Options.Scope.Count > 0)
{
@@ -253,5 +261,66 @@ namespace Owin.Security.Providers.Salesforce
return context.IsRequestCompleted;
}
private string ComposeAuthorizationEndpoint(AuthenticationProperties properties) {
string endpointPath = AuthorizationEndpoint;
string endpoint =
!String.IsNullOrEmpty(Options.Endpoints.AuthorizationEndpoint) ?
Options.Endpoints.AuthorizationEndpoint :
ComposeEndpoint(properties, endpointPath);
// if AuthenticationProperties for this session specifies an environment property
// it should take precedence over the value in AuthenticationOptions
string environmentProperty = null;
if (properties.Dictionary.TryGetValue(Constants.EnvironmentAuthenticationProperty, out environmentProperty)) {
endpoint =
environmentProperty == Constants.SandboxEnvironment ?
SandboxHost + endpointPath :
ProductionHost + endpointPath;
}
return endpoint;
}
private string ComposeTokenEndpoint(AuthenticationProperties properties) {
string endpointPath = TokenEndpoint;
string endpoint =
!String.IsNullOrEmpty(Options.Endpoints.TokenEndpoint) ?
Options.Endpoints.TokenEndpoint :
ComposeEndpoint(properties, endpointPath);
// if AuthenticationProperties for this session specifies an environment property
// it should take precedence over the value in AuthenticationOptions
string environmentProperty = null; ;
if (properties.Dictionary.TryGetValue(Constants.EnvironmentAuthenticationProperty, out environmentProperty)) {
endpoint =
environmentProperty == Constants.SandboxEnvironment ?
SandboxHost + endpointPath :
ProductionHost + endpointPath;
}
return endpoint;
}
private string ComposeEndpoint(AuthenticationProperties properties, string endpointPath) {
string endpoint =
!String.IsNullOrEmpty(Options.Endpoints.Environment) && Options.Endpoints.Environment == Constants.SandboxEnvironment ?
SandboxHost + endpointPath :
ProductionHost + endpointPath;
// if AuthenticationProperties for this session specifies an environment property
// it should take precedence over the value in AuthenticationOptions
string environmentProperty = null; ;
if (properties.Dictionary.TryGetValue(Constants.EnvironmentAuthenticationProperty, out environmentProperty)) {
endpoint =
environmentProperty == Constants.SandboxEnvironment ?
SandboxHost + endpointPath :
ProductionHost + endpointPath;
}
return endpoint;
}
}
}

View File

@@ -19,10 +19,12 @@ namespace Owin.Security.Providers.Salesforce
/// Endpoint which is used to exchange code for access token
/// </summary>
public string TokenEndpoint { get; set; }
}
private const string AuthorizationEndPoint = "";
private const string TokenEndpoint = "";
/// <summary>
/// Production or Sandbox. Use Constants.ProductionEnvironment or Constants.SandboxEnvironment
/// </summary>
public string Environment { get; set; }
}
/// <summary>
/// Gets or sets the a pinned certificate validator to use to validate the endpoints used
@@ -79,8 +81,8 @@ namespace Owin.Security.Providers.Salesforce
public string ClientSecret { get; set; }
/// <summary>
/// Gets the sets of OAuth endpoints used to authenticate against Salesforce. Overriding these endpoints allows you to use Salesforce Enterprise for
/// authentication.
/// Gets the sets of OAuth endpoints used to authenticate against Salesforce.
/// Overriding these endpoints allows you to use Salesforce Enterprise for authentication.
/// </summary>
public SalesforceAuthenticationEndpoints Endpoints { get; set; }
@@ -127,8 +129,8 @@ namespace Owin.Security.Providers.Salesforce
BackchannelTimeout = TimeSpan.FromSeconds(60);
Endpoints = new SalesforceAuthenticationEndpoints
{
AuthorizationEndpoint = AuthorizationEndPoint,
TokenEndpoint = TokenEndpoint
AuthorizationEndpoint = null,
TokenEndpoint = null
};
}
}

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
@@ -46,9 +48,8 @@
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin.Security.Providers.OpenIDBase, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.Security.Providers.OpenIDBase.2.1\lib\net45\Owin.Security.Providers.OpenIDBase.dll</HintPath>
<Private>True</Private>
<Reference Include="Owin.Security.Providers.OpenIDBase, Version=2.0.0.0, Culture=neutral, PublicKeyToken=1328b8c16b108c43, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.Security.Providers.OpenIDBase.2.1.1\lib\net45\Owin.Security.Providers.OpenIDBase.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />

View File

@@ -10,7 +10,7 @@ namespace Owin.Security.Providers.Steam
{
internal sealed class SteamAuthenticationHandler : OpenIDAuthenticationHandlerBase<SteamAuthenticationOptions>
{
private readonly Regex _accountIDRegex = new Regex(@"^http://steamcommunity\.com/openid/id/(7[0-9]{15,25})$", RegexOptions.Compiled);
private readonly Regex _accountIDRegex = new Regex(@"^https?://steamcommunity\.com/openid/id/(7[0-9]{15,25})$", RegexOptions.Compiled);
private const string UserInfoUri = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={0}&steamids={1}";

View File

@@ -4,5 +4,5 @@
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="Owin.Security.Providers.OpenIDBase" version="2.1" targetFramework="net45" />
<package id="Owin.Security.Providers.OpenIDBase" version="2.1.1" targetFramework="net45" />
</packages>

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -20,6 +20,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@@ -28,6 +29,7 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">

View File

@@ -179,6 +179,7 @@ namespace Owin.Security.Providers.Twitch
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&force_verify=" + Options.ForceVerify.ToString().ToLower() +
"&response_type=" + "code" +
"&state=" + Uri.EscapeDataString(state);

View File

@@ -120,6 +120,11 @@ namespace Owin.Security.Providers.Twitch
/// </summary>
public ISecureDataFormat<AuthenticationProperties> StateDataFormat { get; set; }
/// <summary>
/// Gets or sets whether to force verify the user during the OAuth flow
/// </summary>
public bool ForceVerify { get; set; }
/// <summary>
/// Initializes a new <see cref="TwitchAuthenticationOptions" />
/// </summary>

View File

@@ -0,0 +1,7 @@
namespace Owin.Security.Providers.Typeform
{
public static class Constants
{
public const string DefaultAuthenticationType = "Typeform";
}
}

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C8862B45-E1D1-4AB7-A83D-3A2FD2A22526}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.Typeform</RootNamespace>
<AssemblyName>Owin.Security.Providers.Typeform</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<LangVersion>6</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.3.0.1\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Security.3.0.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="TypeformAuthenticationExtensions.cs" />
<Compile Include="TypeformAuthenticationHandler.cs" />
<Compile Include="TypeformAuthenticationMiddleware.cs" />
<Compile Include="TypeformAuthenticationOptions.cs" />
<Compile Include="Provider\ITypeformAuthenticationProvider.cs" />
<Compile Include="Provider\TypeformAuthenticatedContext.cs" />
<Compile Include="Provider\TypeformAuthenticationProvider.cs" />
<Compile Include="Provider\TypeformReturnEndpointContext.cs" />
</ItemGroup>
<ItemGroup>
<None Include="C:\projects\GitHub\OwinOAuthProviders\Owin.Security.Providers.Typeform\Owin.Security.Providers.Typeform.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="PostBuildMacros">
<GetAssemblyIdentity AssemblyFiles="$(TargetPath)">
<Output TaskParameter="Assemblies" ItemName="Targets" />
</GetAssemblyIdentity>
<ItemGroup>
<VersionNumber Include="@(Targets->'%(Version)')" />
</ItemGroup>
</Target>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
<PostBuildEventDependsOn>
$(PostBuildEventDependsOn);
PostBuildMacros;
</PostBuildEventDependsOn>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.Typeform")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.Typeform")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("b6a4a4cb-d365-41a0-b4c9-966e7ef19de0")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -0,0 +1,24 @@
using System.Threading.Tasks;
namespace Owin.Security.Providers.Typeform
{
/// <summary>
/// Specifies callback methods which the <see cref="TypeformAuthenticationMiddleware"></see> invokes to enable developer control over the authentication process. />
/// </summary>
public interface ITypeformAuthenticationProvider
{
/// <summary>
/// Invoked whenever Typeform successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
Task Authenticated(TypeformAuthenticatedContext context);
/// <summary>
/// Invoked prior to the <see cref="System.Security.Claims.ClaimsIdentity"/> being saved in a local cookie and the browser being redirected to the originally requested URL.
/// </summary>
/// <param name="context"></param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
Task ReturnEndpoint(TypeformReturnEndpointContext context);
}
}

View File

@@ -0,0 +1,59 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Linq;
using System.Security.Claims;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
namespace Owin.Security.Providers.Typeform
{
/// <summary>
/// Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.
/// </summary>
public class TypeformAuthenticatedContext : BaseContext
{
/// <summary>
/// Initializes a <see cref="TypeformAuthenticatedContext"/>
/// </summary>
/// <param name="context">The OWIN environment</param>
/// <param name="userJson">The JSON-serialized user</param>
/// <param name="accessToken">Typeform Access token</param>
/// <param name="refreshToken">Typeform Refresh token</param>
/// <param name="instanceUrl">Typeform instance url</param>
public TypeformAuthenticatedContext(IOwinContext context, string accessToken)
: base(context)
{
AccessToken = accessToken;
// Typeform doesn't supply a unique identifier for the user,
// so we generate a fake one because OWIN pipeline requires it
// This means you can only use Typeform OAuth for authorization, not authentication because
// each time you sign in with the same Typeform account this provider will yield a distinct UserId
UserId = Guid.NewGuid().ToString();
}
/// <summary>
/// Gets the Typeform access token
/// </summary>
public string AccessToken { get; private set; }
/// <summary>
/// Gets the Typeform User ID
/// </summary>
[Obsolete("This is not the real UserId because Typeform OAuth endpoint does not provide it. Use Typeform OAuth for authorization, not authentication.")]
public string UserId { get; private set; }
/// <summary>
/// Gets the <see cref="ClaimsIdentity"/> representing the user
/// </summary>
public ClaimsIdentity Identity { get; set; }
/// <summary>
/// Gets or sets a property bag for common authentication properties
/// </summary>
public AuthenticationProperties Properties { get; set; }
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Threading.Tasks;
namespace Owin.Security.Providers.Typeform
{
/// <summary>
/// Default <see cref="ITypeformAuthenticationProvider"/> implementation.
/// </summary>
public class TypeformAuthenticationProvider : ITypeformAuthenticationProvider
{
/// <summary>
/// Initializes a <see cref="TypeformAuthenticationProvider"/>
/// </summary>
public TypeformAuthenticationProvider()
{
OnAuthenticated = context => Task.FromResult<object>(null);
OnReturnEndpoint = context => Task.FromResult<object>(null);
}
/// <summary>
/// Gets or sets the function that is invoked when the Authenticated method is invoked.
/// </summary>
public Func<TypeformAuthenticatedContext, Task> OnAuthenticated { get; set; }
/// <summary>
/// Gets or sets the function that is invoked when the ReturnEndpoint method is invoked.
/// </summary>
public Func<TypeformReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever Typeform successfully authenticates a user
/// </summary>
/// <param name="context">Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.</param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
public virtual Task Authenticated(TypeformAuthenticatedContext context)
{
return OnAuthenticated(context);
}
/// <summary>
/// Invoked prior to the <see cref="System.Security.Claims.ClaimsIdentity"/> being saved in a local cookie and the browser being redirected to the originally requested URL.
/// </summary>
/// <param name="context"></param>
/// <returns>A <see cref="Task"/> representing the completed operation.</returns>
public virtual Task ReturnEndpoint(TypeformReturnEndpointContext context)
{
return OnReturnEndpoint(context);
}
}
}

Some files were not shown because too many files have changed in this diff Show More