Compare commits

...

4 Commits

Author SHA1 Message Date
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
Guillaume
5626c02442 Added provider for Evernote (#197)
* Evernote provider is now available.
Based on Evernote SDK for .NET and the obsolete doc (ie. https://dev.evernote.com/doc/articles/authentication.php) (Step 3 is POST, not GET)

* Fix SyncrhonizationContext deadlock caused by ASP.NET site

* Evernote provider now working trought Xamarin OAuthAuthenticator and Identity Server 3

* Add claims for notestoreuri and accesstoken

* Evernote OK, before cleanup

* Cleanup

* Remove my credentials in demo project.

* Change the default URL to lower case
2017-03-04 20:30:56 -05:00
27 changed files with 1980 additions and 219 deletions

View File

@@ -104,6 +104,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Box
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Baidu", "src\Owin.Security.Providers.Baidu\Owin.Security.Providers.Baidu.csproj", "{E2759807-4D7C-4288-AAC8-F5B7B4616680}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Evernote", "src\Owin.Security.Providers.Evernote\Owin.Security.Providers.Evernote.csproj", "{B8F05057-8B9F-44CE-B983-99CB7C2E9E5A}"
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
Global
@@ -316,6 +318,10 @@ Global
{E2759807-4D7C-4288-AAC8-F5B7B4616680}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2759807-4D7C-4288-AAC8-F5B7B4616680}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E2759807-4D7C-4288-AAC8-F5B7B4616680}.Release|Any CPU.Build.0 = Release|Any CPU
{B8F05057-8B9F-44CE-B983-99CB7C2E9E5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8F05057-8B9F-44CE-B983-99CB7C2E9E5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8F05057-8B9F-44CE-B983-99CB7C2E9E5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8F05057-8B9F-44CE-B983-99CB7C2E9E5A}.Release|Any CPU.Build.0 = Release|Any CPU
{8FD3A9CB-E684-42C0-A8BF-7746FDD3D43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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

View File

@@ -2,6 +2,8 @@
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Owin.Security.Providers.Evernote;
using Owin.Security.Providers.PayPal;
namespace OwinOAuthProvidersDemo
{
@@ -18,277 +20,293 @@ namespace OwinOAuthProvidersDemo
});
// Use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
//app.UseDeviantArtAuthentication("id", "secret");
//app.UseUntappdAuthentication("id", "secret");
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseDeviantArtAuthentication("id", "secret");
//app.UseUntappdAuthentication("id", "secret");
// Uncomment the following lines to enable logging in with third party login providers
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication();
//app.UseGoogleAuthentication();
//app.UseLinkedInAuthentication("", "");
//app.UseLinkedInAuthentication("", "");
//app.UseYahooAuthentication("", "");
//app.UseYahooAuthentication("", "");
//app.UseTripItAuthentication("", "");
//app.UseTripItAuthentication("", "");
//app.UseGitHubAuthentication("", "");
//app.UseGitHubAuthentication("", "");
//app.UseBufferAuthentication("", "");
//app.UseBufferAuthentication("", "");
//app.UseRedditAuthentication("", "");
//app.UseRedditAuthentication("", "");
//app.UseStackExchangeAuthentication(
// clientId: "",
// clientSecret: "",
// key: "");
//app.UseStackExchangeAuthentication(
// clientId: "",
// clientSecret: "",
// key: "");
//app.UseInstagramInAuthentication("", "");
//app.UseInstagramInAuthentication("", "");
//var options = new GooglePlusAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// RequestOfflineAccess = true,
// Provider = new GooglePlusAuthenticationProvider
// {
// OnAuthenticated = async context => System.Diagnostics.Debug.WriteLine(String.Format("Refresh Token: {0}", context.RefreshToken))
// }
//};
//options.MomentTypes.Add("http://schemas.google.com/AddActivity");
//options.MomentTypes.Add("http://schemas.google.com/CheckInActivity");
//options.MomentTypes.Add("http://schemas.google.com/BuyActivity");
//app.UseGooglePlusAuthentication(options);
//var options = new GooglePlusAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// RequestOfflineAccess = true,
// Provider = new GooglePlusAuthenticationProvider
// {
// OnAuthenticated = async context => System.Diagnostics.Debug.WriteLine(String.Format("Refresh Token: {0}", context.RefreshToken))
// }
//};
//options.MomentTypes.Add("http://schemas.google.com/AddActivity");
//options.MomentTypes.Add("http://schemas.google.com/CheckInActivity");
//options.MomentTypes.Add("http://schemas.google.com/BuyActivity");
//app.UseGooglePlusAuthentication(options);
/*
/*
* Twitch sign-ins use /signin-Twitch as the URL for authentication
*
*/
////Simple Twitch Sign-in
//app.UseTwitchAuthentication("", "");
////Simple Twitch Sign-in
//app.UseTwitchAuthentication("", "");
////More complex Twitch Sign-in
//var opt = new TwitchAuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = "",
// Provider = new TwitchAuthenticationProvider()
// {
// OnAuthenticated = async z =>
// {
//// Getting the twitch users picture
// z.Identity.AddClaim(new Claim("Picture", z.User.GetValue("logo").ToString()));
// }
//// You should be able to access these claims with HttpContext.GetOwinContext().Authentication.GetExternalLoginInfoAsync().Claims in your Account Controller
// // Commonly used in the ExternalLoginCallback() in AccountController.cs
// /*
////More complex Twitch Sign-in
//var opt = new TwitchAuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = "",
// Provider = new TwitchAuthenticationProvider()
// {
// OnAuthenticated = async z =>
// {
//// Getting the twitch users picture
// z.Identity.AddClaim(new Claim("Picture", z.User.GetValue("logo").ToString()));
// }
//// You should be able to access these claims with HttpContext.GetOwinContext().Authentication.GetExternalLoginInfoAsync().Claims in your Account Controller
// // Commonly used in the ExternalLoginCallback() in AccountController.cs
// /*
// if (user != null)
// {
// var claim = (await AuthenticationManager.GetExternalLoginInfoAsync()).ExternalIdentity.Claims.First(
// a => a.Type == "Picture");
// user.Claims.Add(new IdentityUserClaim() { ClaimType = claim.Type, ClaimValue = claim.Value });
// await SignInAsync(user, isPersistent: false);
// return RedirectToLocal(returnUrl);
// }
// */
// }
//};
//app.UseTwitchAuthentication(opt);
// if (user != null)
// {
// var claim = (await AuthenticationManager.GetExternalLoginInfoAsync()).ExternalIdentity.Claims.First(
// a => a.Type == "Picture");
// user.Claims.Add(new IdentityUserClaim() { ClaimType = claim.Type, ClaimValue = claim.Value });
// await SignInAsync(user, isPersistent: false);
// return RedirectToLocal(returnUrl);
// }
// */
// }
//};
//app.UseTwitchAuthentication(opt);
//app.UseOpenIDAuthentication("http://me.yahoo.com/", "Yahoo");
//app.UseOpenIDAuthentication("http://me.yahoo.com/", "Yahoo");
//app.UseOpenIDAuthentication("https://openid.stackexchange.com/", "StackExchange");
//app.UseOpenIDAuthentication("https://openid.stackexchange.com/", "StackExchange");
//app.UseOpenIDAuthentication("https://www.google.com/accounts/o8/id", "Google");
//app.UseOpenIDAuthentication("https://www.google.com/accounts/o8/id", "Google");
//app.UseSteamAuthentication(applicationKey: "");
//app.UseSteamAuthentication(applicationKey: "");
//app.UseOpenIDAuthentication("http://orange.fr", "Orange");
// Use OpenId provider login uri instead of discovery uri
//app.UseOpenIDAuthentication("http://openid.orange.fr/server", "Orange", true);
//app.UseOpenIDAuthentication("http://orange.fr", "Orange");
// Use OpenId provider login uri instead of discovery uri
//app.UseOpenIDAuthentication("http://openid.orange.fr/server", "Orange", true);
//app.UseSalesforceAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseSalesforceAuthentication(
// clientId: "",
// clientSecret: "");
//in scenarios where a sandbox URL needs to be used
//var salesforceOptions = new SalesforceAuthenticationOptions
//{
// Endpoints =
// new SalesforceAuthenticationOptions.SalesforceAuthenticationEndpoints
// {
// AuthorizationEndpoint =
// "https://ap1.salesforce.com/services/oauth2/authorize",
// TokenEndpoint = "https://ap1.salesforce.com/services/oauth2/token"
// },
// 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);
// }
// }
//};
//app.UseSalesforceAuthentication(salesforceOptions);
//in scenarios where a sandbox URL needs to be used
//var salesforceOptions = new SalesforceAuthenticationOptions
//{
// Endpoints =
// new SalesforceAuthenticationOptions.SalesforceAuthenticationEndpoints
// {
// AuthorizationEndpoint =
// "https://ap1.salesforce.com/services/oauth2/authorize",
// TokenEndpoint = "https://ap1.salesforce.com/services/oauth2/token"
// },
// 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);
// }
// }
//};
//app.UseSalesforceAuthentication(salesforceOptions);
////app.UseShopifyAuthentication("", "");
////app.UseShopifyAuthentication("", "");
//app.UseArcGISOnlineAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseArcGISOnlineAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseWordPressAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseWordPressAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseDropboxAuthentication(
// appKey: "",
// appSecret: "");
//app.UseDropboxAuthentication(
// appKey: "",
// appSecret: "");
//app.UseHealthGraphAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseHealthGraphAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseBoxAuthentication(
// appKey: "",
// appSecret: "");
//app.UseBoxAuthentication(
// appKey: "",
// appSecret: "");
//app.UseBaiduAuthentication(
// apiKey: "",
// secretKey: "");
//app.UseBaiduAuthentication(
// apiKey: "",
// secretKey: "");
//app.UseBattleNetAuthentication(new BattleNetAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseBattleNetAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseBattleNetAuthentication(new BattleNetAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseBattleNetAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseAsanaAuthentication("", "");
//app.UseAsanaAuthentication("", "");
//app.UseEveOnlineAuthentication("", "");
//app.UseEveOnlineAuthentication("", "");
//app.UseSoundCloudAuthentication("", "");
//app.UseSoundCloudAuthentication("", "");
//app.UseFoursquareAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseFoursquareAuthentication(
// 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.UseWargamingAccountAuthentication("", WargamingAuthenticationOptions.Region.NorthAmerica);
// app.UsePayPalAuthentication(payPalOptions);
//app.UseFlickrAuthentication("", "");
//app.UseVisualStudioAuthentication(
// appId: "",
// appSecret: "");
//app.UseWargamingAccountAuthentication("", WargamingAuthenticationOptions.Region.NorthAmerica);
//app.UseSpotifyAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseFlickrAuthentication("", "");
//app.UseVisualStudioAuthentication(
// appId: "",
// appSecret: "");
//var options = new SlackAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// TeamId = "" // optional
//};
//options.Scope.Add("identify");
//app.UseSlackAuthentication(options);
//app.UseSpotifyAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseGitterAuthentication(
// clientId: "",
// clientSecret: ""
//);
//var options = new SlackAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// TeamId = "" // optional
//};
//options.Scope.Add("identify");
//app.UseSlackAuthentication(options);
//app.UseImgurAuthentication(
// new ImgurAuthenticationOptions
// {
// ClientId = "",
// ClientSecret = ""
// });
//app.UseGitterAuthentication(
// clientId: "",
// clientSecret: ""
//);
//var options = new BacklogAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// ContractName = "",
// CallbackPath = new PathString(""), // ex.new PathString("/OauthTokenRequest")
// Provider = new BacklogAuthenticationProvider
// {
// OnAuthenticated = async context => await System.Threading.Tasks.Task.Run(()=> { System.Diagnostics.Debug.WriteLine(String.Format("Refresh Token: {0}", context.RefreshToken)); })
// }
//};
//app.UseImgurAuthentication(
// new ImgurAuthenticationOptions
// {
// ClientId = "",
// ClientSecret = ""
// });
//app.UseBacklogAuthentication(options);
//var options = new BacklogAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = "",
// ContractName = "",
// CallbackPath = new PathString(""), // ex.new PathString("/OauthTokenRequest")
// Provider = new BacklogAuthenticationProvider
// {
// OnAuthenticated = async context => await System.Threading.Tasks.Task.Run(()=> { System.Diagnostics.Debug.WriteLine(String.Format("Refresh Token: {0}", context.RefreshToken)); })
// }
//};
//var cosignOptions = new CosignAuthenticationOptions
//{
// AuthenticationType = "Cosign",
// SignInAsAuthenticationType = signInAsType,
// CosignServer = "weblogin.umich.edu",
// CosignServicePort = 6663,
// IdentityServerHostInstance = "core1",
// ClientServer = "cosignservername"
//};
//app.UseCosignAuthentication(cosignOptions);
//app.UseBacklogAuthentication(options);
//app.UseVimeoAuthentication("", "");
//var cosignOptions = new CosignAuthenticationOptions
//{
// AuthenticationType = "Cosign",
// SignInAsAuthenticationType = signInAsType,
// CosignServer = "weblogin.umich.edu",
// CosignServicePort = 6663,
// IdentityServerHostInstance = "core1",
// ClientServer = "cosignservername"
//};
//app.UseCosignAuthentication(cosignOptions);
//app.UseFitbitAuthentication(new FitbitAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseVimeoAuthentication("", "");
//app.UseOnshapeAuthentication(
// appKey: "",
// appSecret: "");
//
//
//app.UseOnshapeAuthentication(new OnshapeAuthenticationOptions()
//{
// AppKey = "",
// AppSecret = "",
// CallbackPath = new PathString("/oauthRedirect"),
// Hostname = "partner.dev.onshape.com"
//});
//app.UseFitbitAuthentication(new FitbitAuthenticationOptions
//{
// ClientId = "",
// ClientSecret = ""
//});
//app.UseVKontakteAuthentication("", "");
//app.UseOnshapeAuthentication(
// appKey: "",
// appSecret: "");
//
//
//app.UseOnshapeAuthentication(new OnshapeAuthenticationOptions()
//{
// AppKey = "",
// AppSecret = "",
// CallbackPath = new PathString("/oauthRedirect"),
// Hostname = "partner.dev.onshape.com"
//});
//app.UseXingAuthentication("", "");
//app.UseVKontakteAuthentication("", "");
//app.UseDoYouBuzzAuthentication("", "");
//app.("", "");
//app.UseOrcidAuthentication("","");
//app.UseXingAuthentication("", "");
//app.UseDiscordAuthentication("", "");
//app.UseGeniAuthentication("", "");
//app.UseMyHeritageAuthentication("", "");
//app.UseDoYouBuzzAuthentication("", "");
//app.("", "");
//app.UseOrcidAuthentication("","");
//app.UseWSO2Authentication("", "", "");
//app.UseDiscordAuthentication("", "");
//app.UseGeniAuthentication("", "");
//app.UseMyHeritageAuthentication("", "");
}
//app.UseWSO2Authentication("", "", "");
//app.UseEvernoteAuthentication(new EvernoteAuthenticationOptions()
//{
// IsSandBox = true,
// AppKey = "",
// AppSecret = ""
//});
}
}
}

View File

@@ -251,6 +251,216 @@
<ItemGroup>
<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.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.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.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>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -15,7 +15,7 @@ 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.14.0"
PROJECTS = Dir.glob('src/*').select{|dir| File.directory? dir }
desc 'Retrieve things'
@@ -27,7 +27,6 @@ task :build => [:retrieve, :compile]
desc 'clean, retrieve, build, generate nuspecs'
task :preflight => [:clean, :build, :nuspec_gen]
desc 'publish'
task :publish => [:preflight,:nuspec_gen, :nuspec_pack, :nuspec_publish]

View File

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

View File

@@ -0,0 +1,29 @@
using System;
namespace Owin.Security.Providers.Evernote
{
public static class EvernoteAuthenticationExtensions
{
public static IAppBuilder UseEvernoteAuthentication(this IAppBuilder app,
EvernoteAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException(nameof(options));
app.Use(typeof(EvernoteAuthenticationMiddleware), app, options);
return app;
}
public static IAppBuilder UseEvernoteAuthentication(this IAppBuilder app, string appKey, string appSecret)
{
return app.UseEvernoteAuthentication(new EvernoteAuthenticationOptions
{
AppKey = appKey,
AppSecret = appSecret
});
}
}
}

View File

@@ -0,0 +1,379 @@
using EvernoteSDK;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Evernote.Messages;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Net.Http;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Owin.Security.Providers.Evernote
{
public class EvernoteAuthenticationHandler : AuthenticationHandler<EvernoteAuthenticationOptions>
{
private const string StateCookie = "_EvernoteState";
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string RequestTokenEndpoint = "/oauth";
private const string AuthenticationEndpoint = "/OAuth.action?oauth_token=";
private const string AccessTokenEndpoint = "/oauth";
private const string ProductionBase = "https://www.evernote.com";
private const string SandBoxBase = "https://sandbox.evernote.com";
public string BaseUri => Options.IsSandBox ? SandBoxBase : ProductionBase;
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public EvernoteAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
_httpClient = httpClient;
_logger = logger;
_logger.WriteInformation("Authentication Handler initialized");
}
public override async Task<bool> InvokeAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
return await InvokeReturnPathAsync();
}
return false;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
var query = Request.Query;
var protectedRequestToken = Request.Cookies[StateCookie];
var requestToken = Options.StateDataFormat.Unprotect(protectedRequestToken);
if (requestToken == null)
{
_logger.WriteWarning("Invalid state");
return null;
}
properties = requestToken.Properties;
var returnedToken = query.Get("oauth_token");
if (string.IsNullOrWhiteSpace(returnedToken))
{
_logger.WriteWarning("Missing oauth_token");
return new AuthenticationTicket(null, properties);
}
if (returnedToken != requestToken.Token)
{
_logger.WriteWarning("Unmatched token");
return new AuthenticationTicket(null, properties);
}
var oauthVerifier = query.Get("oauth_verifier");
if (string.IsNullOrWhiteSpace(oauthVerifier))
{
_logger.WriteWarning("Missing or blank oauth_verifier");
return new AuthenticationTicket(null, properties);
}
// Retrieve access token
var accessToken = await ObtainAccessTokenAsync(Options.AppKey, Options.AppSecret, requestToken, oauthVerifier);
// Retrieve user infos
var userName = GetUserInfos(accessToken);
var context = new EvernoteAuthenticatedContext(Context, accessToken)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
if (!string.IsNullOrEmpty(context.UserId))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.UserId, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(userName))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Name, userName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.NoteStoreUrl))
{
context.Identity.AddClaim(new Claim("urn:evernote:notestoreuri", context.NoteStoreUrl, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:evernote:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Properties = requestToken.Properties;
Response.Cookies.Delete(StateCookie);
await Options.Provider.Authenticated(context);
return new AuthenticationTicket(context.Identity, context.Properties);
}
catch (Exception ex)
{
_logger.WriteError("Authentication failed", ex);
return new AuthenticationTicket(null, properties);
}
}
private string GetUserInfos(AccessToken accessToken)
{
ENSession.SetSharedSessionDeveloperToken(accessToken.Token, accessToken.NoteStoreUrl);
var session = new ENSession();
session.PerformPostAuthentication();
return session.UserDisplayName;
}
protected override async Task ApplyResponseChallengeAsync()
{
_logger.WriteInformation("Applying response challenge");
if (Response.StatusCode != 401)
{
return;
}
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge == null) return;
var baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
var callBackUri = baseUri + Options.CallbackPath;
var properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = baseUri + Request.Path + Request.QueryString;
}
_logger.WriteInformation("Requesting Token...");
var requestToken = await ObtainRequestTokenAsync(Options.AppKey, Options.AppSecret, callBackUri, properties);
_logger.WriteInformation("Token request successfull. Token: " + requestToken.Token);
var authorizationEndpoint = BaseUri + AuthenticationEndpoint + requestToken.Token;
if (requestToken.CallbackConfirmed)
{
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Secure = Request.IsSecure
};
Response.StatusCode = 302;
Response.Cookies.Append(StateCookie, Options.StateDataFormat.Protect(requestToken), cookieOptions);
Response.Headers.Set("Location", authorizationEndpoint);
}
else
{
_logger.WriteError("requestToken CallbackConfirmed!=true");
}
}
private async Task<RequestToken> ObtainRequestTokenAsync(string appKey, string appSecret, string callBackUri, AuthenticationProperties properties)
{
string normalizedUrl;
string normalizedRequestParameters;
var oauthBase = new OAuthBase();
var url = new Uri(BaseUri + RequestTokenEndpoint);
var signature = oauthBase.GenerateSignature(
url,
appKey,
appSecret,
null,
null,
"GET",
oauthBase.GenerateTimeStamp(),
oauthBase.GenerateNonce(),
callBackUri, out normalizedUrl, out normalizedRequestParameters);
normalizedRequestParameters = normalizedRequestParameters + "&oauth_signature=" + HttpUtility.UrlEncode(signature);
if (normalizedRequestParameters.Length > 0)
normalizedUrl += "?";
var authorizationEndpoint = normalizedUrl + normalizedRequestParameters;
_logger.WriteInformation("Url =" + authorizationEndpoint);
string query = await WebRequestAsync(HttpMethod.Get, authorizationEndpoint, null);
if (query?.Length > 0)
{
NameValueCollection queryString = HttpUtility.ParseQueryString(query);
if (queryString["oauth_token"] != null)
{
_logger.WriteInformation("Retrieving data...");
return new RequestToken
{
Token = Uri.UnescapeDataString(queryString["oauth_token"]),
CallbackConfirmed = true,
Properties = properties
};
}
}
return new RequestToken();
}
private async Task<bool> InvokeReturnPathAsync()
{
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 EvernoteReturnEndpointContext(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;
}
private async Task<AccessToken> ObtainAccessTokenAsync(string appKey, string appSecret, RequestToken token, string verifier)
{
string normalizedUrl;
string normalizedRequestParameters;
var oauthBase = new OAuthBase();
var url = new Uri(BaseUri + AccessTokenEndpoint);
var signature = oauthBase.GenerateSignature(
url,
appKey,
appSecret,
token.Token,
verifier,
"POST",
oauthBase.GenerateTimeStamp(),
oauthBase.GenerateNonce(),
"",
out normalizedUrl, out normalizedRequestParameters);
var postData = normalizedRequestParameters + "&oauth_signature=" + HttpUtility.UrlEncode(signature);
var authorizationParts = new SortedDictionary<string, string>();
foreach (var key in postData.Split('&'))
{
authorizationParts.Add(key.Split('=')[0], key.Split('=')[1]);
}
var authorizationHeaderBuilder = new StringBuilder();
authorizationHeaderBuilder.Append("OAuth ");
foreach (var authorizationPart in authorizationParts)
{
authorizationHeaderBuilder.AppendFormat(
"{0}=\"{1}\", ", authorizationPart.Key, Uri.EscapeDataString(authorizationPart.Value));
}
authorizationHeaderBuilder.Length = authorizationHeaderBuilder.Length - 2;
string query = await WebRequestAsync(HttpMethod.Post, normalizedUrl, authorizationHeaderBuilder.ToString());
if (query.Length > 0)
{
var responseParameters = HttpUtility.ParseQueryString(query);
if (responseParameters["oauth_token"] != null)
{
return new AccessToken
{
Token = Uri.UnescapeDataString(responseParameters["oauth_token"]),
Shard = Uri.UnescapeDataString(responseParameters["edam_shard"]),
UserId = Uri.UnescapeDataString(responseParameters["edam_userId"]),
NoteStoreUrl = Uri.UnescapeDataString(responseParameters["edam_noteStoreUrl"]),
WebApiUrlPrefix = Uri.UnescapeDataString(responseParameters["edam_webApiUrlPrefix"]),
};
}
}
return new AccessToken();
}
private Task<string> WebRequestAsync(HttpMethod method, string url, string postData)
{
try
{
var request = new HttpRequestMessage(method, url);
if (method == HttpMethod.Post)
request.Headers.Add("Authorization", postData);
_logger.WriteInformation("Send request...");
var response = _httpClient.SendAsync(request, Request.CallCancelled).Result;
_logger.WriteInformation("Request ended");
response.EnsureSuccessStatusCode();
return response.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
_logger.WriteError(ex.Message, ex);
}
return null;
}
}
}

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.DataHandler.Encoder;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Evernote.Messages;
namespace Owin.Security.Providers.Evernote
{
public class EvernoteAuthenticationMiddleware : AuthenticationMiddleware<EvernoteAuthenticationOptions>
{
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public EvernoteAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
EvernoteAuthenticationOptions options)
: base(next, options)
{
if (string.IsNullOrWhiteSpace(Options.AppKey))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "AppKey"));
if (string.IsNullOrWhiteSpace(Options.AppSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "AppSecret"));
_logger = app.CreateLogger<EvernoteAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new EvernoteAuthenticationProvider();
if (Options.StateDataFormat == null)
{
var dataProtector = app.CreateDataProtector(
typeof (EvernoteAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new SecureDataFormat<RequestToken>(
Serializers.RequestToken,
dataProtector,
TextEncodings.Base64Url);
}
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.Evernote.EvernoteAuthenticationOptions" /> supplied to the constructor.
/// </returns>
protected override AuthenticationHandler<EvernoteAuthenticationOptions> CreateHandler()
{
return new EvernoteAuthenticationHandler(_httpClient, _logger);
}
private static HttpMessageHandler ResolveHttpMessageHandler(EvernoteAuthenticationOptions 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,98 @@
using System;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Owin.Security.Providers.Evernote.Messages;
namespace Owin.Security.Providers.Evernote
{
public class EvernoteAuthenticationOptions : AuthenticationOptions
{
/// <summary>
/// Gets or sets the a pinned certificate validator to use to validate the endpoints used
/// in back channel communications belong to Evernote
/// </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 Evernote.
/// 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 Evernote.
/// </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-Evernote".
/// </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 Evernote supplied Application Key
/// </summary>
public string AppKey { get; set; }
/// <summary>
/// Gets or sets the Evernote supplied Application Secret
/// </summary>
public string AppSecret { get; set; }
/// <summary>
/// Gets or sets the Evernote sandbox mode
/// </summary>
public bool IsSandBox { get; set; }
/// <summary>
/// Gets or sets the <see cref="IEvernoteAuthenticationProvider" /> used in the authentication events
/// </summary>
public IEvernoteAuthenticationProvider 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<RequestToken> StateDataFormat { get; set; }
/// <summary>
/// Initializes a new <see cref="EvernoteAuthenticationOptions" />
/// </summary>
public EvernoteAuthenticationOptions()
: base("Evernote")
{
Caption = Constants.DefaultAuthenticationType;
CallbackPath = new PathString("/signin-evernote");
AuthenticationMode = AuthenticationMode.Passive;
BackchannelTimeout = TimeSpan.FromSeconds(60);
}
}
}

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.
namespace Owin.Security.Providers.Evernote.Messages
{
/// <summary>
/// Evernote access token
/// </summary>
public class AccessToken : RequestToken
{
/// <summary>
/// Gets or sets the Evernote User ID
/// </summary>
public string UserId { get; set; }
/// <summary>
/// Gets or sets the Evernote User Name
/// </summary>
public string UserName { get; set; }
public string Shard { get; set; }
public string NoteStoreUrl { get; set; }
public string WebApiUrlPrefix { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Owin.Security;
namespace Owin.Security.Providers.Evernote.Messages
{
/// <summary>
/// Yahoo request token
/// </summary>
public class RequestToken
{
/// <summary>
/// Gets or sets the Yahoo token
/// </summary>
public string Token { get; set; }
public bool CallbackConfirmed { get; set; }
/// <summary>
/// Gets or sets a property bag for common authentication properties
/// </summary>
public AuthenticationProperties Properties { get; set; }
}
}

View File

@@ -0,0 +1,103 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using Microsoft.Owin.Security.DataHandler.Serializer;
namespace Owin.Security.Providers.Evernote.Messages
{
/// <summary>
/// Serializes and deserializes Yahoo request and access tokens so that they can be used by other application components.
/// </summary>
public class RequestTokenSerializer : IDataSerializer<RequestToken>
{
private const int FormatVersion = 1;
/// <summary>
/// Serialize a request token
/// </summary>
/// <param name="model">The token to serialize</param>
/// <returns>A byte array containing the serialized token</returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Dispose is idempotent")]
public virtual byte[] Serialize(RequestToken model)
{
using (var memory = new MemoryStream())
{
using (var writer = new BinaryWriter(memory))
{
Write(writer, model);
writer.Flush();
return memory.ToArray();
}
}
}
/// <summary>
/// Deserializes a request token
/// </summary>
/// <param name="data">A byte array containing the serialized token</param>
/// <returns>The Yahoo request token</returns>
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "Dispose is idempotent")]
public virtual RequestToken Deserialize(byte[] data)
{
using (var memory = new MemoryStream(data))
{
using (var reader = new BinaryReader(memory))
{
return Read(reader);
}
}
}
/// <summary>
/// Writes a Yahoo request token as a series of bytes. Used by the <see cref="Serialize"/> method.
/// </summary>
/// <param name="writer">The writer to use in writing the token</param>
/// <param name="token">The token to write</param>
public static void Write(BinaryWriter writer, RequestToken token)
{
if (writer == null)
{
throw new ArgumentNullException(nameof(writer));
}
if (token == null)
{
throw new ArgumentNullException(nameof(token));
}
writer.Write(FormatVersion);
writer.Write(token.Token);
writer.Write(token.CallbackConfirmed);
PropertiesSerializer.Write(writer, token.Properties);
}
/// <summary>
/// Reads a Yahoo request token from a series of bytes. Used by the <see cref="Deserialize"/> method.
/// </summary>
/// <param name="reader">The reader to use in reading the token bytes</param>
/// <returns>The token</returns>
public static RequestToken Read(BinaryReader reader)
{
if (reader == null)
{
throw new ArgumentNullException(nameof(reader));
}
if (reader.ReadInt32() != FormatVersion)
{
return null;
}
var token = reader.ReadString();
var callbackConfirmed = reader.ReadBoolean();
var properties = PropertiesSerializer.Read(reader);
if (properties == null)
{
return null;
}
return new RequestToken { Token = token, CallbackConfirmed = callbackConfirmed, Properties = properties };
}
}
}

View File

@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using Microsoft.Owin.Security.DataHandler.Serializer;
namespace Owin.Security.Providers.Evernote.Messages
{
/// <summary>
/// Provides access to a request token serializer
/// </summary>
public static class Serializers
{
static Serializers()
{
RequestToken = new RequestTokenSerializer();
}
/// <summary>
/// Gets or sets a statically-avaliable serializer object. The value for this property will be <see cref="RequestTokenSerializer"/> by default.
/// </summary>
public static IDataSerializer<RequestToken> RequestToken { get; set; }
}
}

View File

@@ -0,0 +1,177 @@
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Web;
namespace Owin.Security.Providers.Evernote
{
internal sealed class OAuthBase
{
private readonly Random _random = new Random();
private readonly string _unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
private const string OAuthConsumerKey = "oauth_consumer_key";
private const string OAuthCallbackKey = "oauth_callback";
private const string OAuthSignatureMethodKey = "oauth_signature_method";
private const string OAuthTimestampKey = "oauth_timestamp";
private const string OAuthNonceKey = "oauth_nonce";
private const string OAuthTokenKey = "oauth_token";
private const string OAuthVerifierKey = "oauth_verifier";
private const string Hmacsha1SignatureType = "HMAC-SHA1";
private const string PlainTextSignatureType = "PLAINTEXT";
private string ComputeHash(HashAlgorithm hashAlgorithm, string data)
{
if (hashAlgorithm == null)
throw new ArgumentNullException("hashAlgorithm");
if (string.IsNullOrEmpty(data))
throw new ArgumentNullException("data");
byte[] bytes = Encoding.ASCII.GetBytes(data);
return Convert.ToBase64String(hashAlgorithm.ComputeHash(bytes));
}
private List<QueryParameter> GetQueryParameters(string parameters)
{
if (parameters.StartsWith("?"))
parameters = parameters.Remove(0, 1);
List<QueryParameter> queryParameterList = new List<QueryParameter>();
if (!string.IsNullOrEmpty(parameters))
{
string str = parameters;
char[] chArray = { '&' };
foreach (string name in str.Split(chArray))
{
if (!string.IsNullOrEmpty(name) && !name.StartsWith("oauth_"))
{
if (name.IndexOf('=') > -1)
{
string[] strArray = name.Split('=');
queryParameterList.Add(new QueryParameter(strArray[0], strArray[1]));
}
else
queryParameterList.Add(new QueryParameter(name, string.Empty));
}
}
}
return queryParameterList;
}
private string UrlEncode(string value)
{
var stringBuilder = new StringBuilder();
foreach (char ch in value)
{
if (_unreservedChars.IndexOf(ch) != -1)
stringBuilder.Append(ch);
else
stringBuilder.Append(37 + $"{(int) ch:X2}");
}
return stringBuilder.ToString();
}
private string NormalizeRequestParameters(IList<QueryParameter> parameters)
{
StringBuilder stringBuilder = new StringBuilder();
for (int index = 0; index < parameters.Count; ++index)
{
QueryParameter queryParameter = parameters[index];
stringBuilder.AppendFormat("{0}={1}", queryParameter.Name, queryParameter.Value);
if (index < parameters.Count - 1)
stringBuilder.Append("&");
}
return stringBuilder.ToString();
}
private string GenerateSignatureBase(Uri url, string consumerKey, string token, string verifier, string httpMethod, string timeStamp, string nonce, string callback, string signatureType, out string normalizedUrl, out string normalizedRequestParameters)
{
if (token == null)
token = string.Empty;
if (string.IsNullOrEmpty(consumerKey))
throw new ArgumentNullException("consumerKey");
if (string.IsNullOrEmpty(httpMethod))
throw new ArgumentNullException("httpMethod");
if (string.IsNullOrEmpty(signatureType))
throw new ArgumentNullException("signatureType");
List<QueryParameter> queryParameters = GetQueryParameters(url.Query);
queryParameters.Add(new QueryParameter(OAuthConsumerKey, consumerKey));
queryParameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
queryParameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
queryParameters.Add(new QueryParameter(OAuthNonceKey, nonce));
if (!string.IsNullOrEmpty(callback))
queryParameters.Add(new QueryParameter(OAuthCallbackKey, callback));
if (!string.IsNullOrEmpty(token))
queryParameters.Add(new QueryParameter(OAuthTokenKey, token));
if (!string.IsNullOrEmpty(verifier))
queryParameters.Add(new QueryParameter(OAuthVerifierKey, verifier));
normalizedUrl = $"{url.Scheme}://{url.Host}";
normalizedUrl += url.AbsolutePath;
normalizedRequestParameters = NormalizeRequestParameters(queryParameters);
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.AppendFormat("{0}&", httpMethod.ToUpperInvariant());
stringBuilder.AppendFormat("{0}&", UrlEncode(normalizedUrl));
stringBuilder.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
return stringBuilder.ToString();
}
private string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash)
{
return ComputeHash(hash, signatureBase);
}
public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string verifier, string httpMethod, string timeStamp, string nonce, string callback, out string normalizedUrl, out string normalizedRequestParameters)
{
return GenerateSignature(url, consumerKey, consumerSecret, token, verifier, httpMethod, timeStamp, nonce, callback, SignatureTypes.Plaintext, out normalizedUrl, out normalizedRequestParameters);
}
public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string verifier, string httpMethod, string timeStamp, string nonce, string callback, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters)
{
normalizedUrl = null;
normalizedRequestParameters = null;
switch (signatureType)
{
case SignatureTypes.Hmacsha1:
var signatureBase = GenerateSignatureBase(url, consumerKey, token, verifier, httpMethod, timeStamp, nonce, callback, Hmacsha1SignatureType, out normalizedUrl, out normalizedRequestParameters);
var hmacshA1 = new HMACSHA1
{
Key = Encoding.ASCII.GetBytes($"{UrlEncode(consumerSecret)}&{UrlEncode(verifier)}")
};
return GenerateSignatureUsingHash(signatureBase, hmacshA1);
case SignatureTypes.Plaintext:
GenerateSignatureBase(url, consumerKey, token, verifier, httpMethod, timeStamp, nonce, callback, PlainTextSignatureType, out normalizedUrl, out normalizedRequestParameters);
return HttpUtility.UrlEncode($"{consumerSecret}&{verifier}");
case SignatureTypes.Rsasha1:
throw new NotImplementedException();
default:
throw new ArgumentException(@"Unknown signature type", nameof(signatureType));
}
}
public string GenerateTimeStamp()
{
return Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds).ToString();
}
public string GenerateNonce()
{
return _random.Next(123400, 9999999).ToString();
}
private class QueryParameter
{
public string Name { get; }
public string Value { get; }
public QueryParameter(string name, string value)
{
Name = name;
Value = value;
}
}
}
}

View File

@@ -0,0 +1,134 @@
<?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>{B8F05057-8B9F-44CE-B983-99CB7C2E9E5A}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.Evernote</RootNamespace>
<AssemblyName>Owin.Security.Providers.Evernote</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</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="Accessibility" />
<Reference Include="CsQuery, Version=1.3.3.249, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\CsQuery.1.3.4\lib\net40\CsQuery.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="en-html2enml, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\evernote-cloud-sdk-windows.1.0.8\lib\net40\en-html2enml.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Evernote, Version=1.0.5377.16918, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\evernote-cloud-sdk-windows.1.0.8\lib\net40\Evernote.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EvernoteOAuthNet, Version=2.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\evernote-cloud-sdk-windows.1.0.8\lib\net40\EvernoteOAuthNet.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EvernoteSDK, Version=1.0.12.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\evernote-cloud-sdk-windows.1.0.8\lib\net40\EvernoteSDK.dll</HintPath>
<Private>True</Private>
</Reference>
<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=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\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="PreMailer.Net, Version=1.2.7.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\PreMailer.Net.1.2.7\lib\net40\PreMailer.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="SgmlReaderDll, Version=1.8.11.0, Culture=neutral, PublicKeyToken=46b2db9ca481831b, processorArchitecture=MSIL">
<HintPath>..\..\packages\SgmlReader.1.8.11\lib\4.0\SgmlReaderDll.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" />
<Reference Include="Thrift, Version=0.8.0.16918, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\evernote-cloud-sdk-windows.1.0.8\lib\net40\Thrift.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Constants.cs" />
<Compile Include="EvernoteAuthenticationExtensions.cs" />
<Compile Include="EvernoteAuthenticationHandler.cs" />
<Compile Include="EvernoteAuthenticationMiddleware.cs" />
<Compile Include="EvernoteAuthenticationOptions.cs" />
<Compile Include="Messages\AccessToken.cs" />
<Compile Include="Messages\RequestToken.cs" />
<Compile Include="Messages\RequestTokenSerializer.cs" />
<Compile Include="Messages\Serializers.cs" />
<Compile Include="OAuthBase.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Provider\EvernoteAuthenticatedContext.cs" />
<Compile Include="Provider\EvernoteAuthenticationProvider.cs" />
<Compile Include="Provider\EvernoteReturnEndpointContext.cs" />
<Compile Include="Provider\IEvernoteAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
</Compile>
<Compile Include="SignatureTypes.cs" />
</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" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

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.Evernote")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.Evernote")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[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("b8f05057-8b9f-44ce-b983-99cb7c2e9e5a")]
// 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,57 @@
// 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.Evernote.Messages;
namespace Owin.Security.Providers.Evernote
{
/// <summary>
/// Contains information about the login session as well as the user <see cref="System.Security.Claims.ClaimsIdentity"/>.
/// </summary>
public class EvernoteAuthenticatedContext : BaseContext
{
/// <summary>
/// Initializes a <see cref="EvernoteAuthenticatedContext"/>
/// </summary>
/// <param name="context">The OWIN environment</param>
/// <param name="accessToken">Evernote access toke</param>
public EvernoteAuthenticatedContext(IOwinContext context, AccessToken accessToken)
: base(context)
{
UserId = accessToken.UserId;
UserName = accessToken.UserName;
AccessToken = accessToken.Token;
NoteStoreUrl = accessToken.NoteStoreUrl;
}
/// <summary>
/// Gets the Evernote user ID
/// </summary>
public string UserId { get; private set; }
/// <summary>
/// Gets the Evernote username
/// </summary>
public string UserName { get; set; }
/// <summary>
/// Gets the Evernote access token
/// </summary>
public string AccessToken { get; private set; }
public string NoteStoreUrl { get; 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.Evernote
{
/// <summary>
/// Default <see cref="IEvernoteAuthenticationProvider"/> implementation.
/// </summary>
public class EvernoteAuthenticationProvider : IEvernoteAuthenticationProvider
{
/// <summary>
/// Initializes a <see cref="EvernoteAuthenticationProvider"/>
/// </summary>
public EvernoteAuthenticationProvider()
{
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<EvernoteAuthenticatedContext, Task> OnAuthenticated { get; set; }
/// <summary>
/// Gets or sets the function that is invoked when the ReturnEndpoint method is invoked.
/// </summary>
public Func<EvernoteReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever Evernote 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(EvernoteAuthenticatedContext 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(EvernoteReturnEndpointContext 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.Evernote
{
/// <summary>
/// Provides context information to middleware providers.
/// </summary>
public class EvernoteReturnEndpointContext : ReturnEndpointContext
{
/// <summary>
///
/// </summary>
/// <param name="context">OWIN environment</param>
/// <param name="ticket">The authentication ticket</param>
public EvernoteReturnEndpointContext(
IOwinContext context,
AuthenticationTicket ticket)
: base(context, ticket)
{
}
}
}

View File

@@ -0,0 +1,24 @@
using System.Threading.Tasks;
namespace Owin.Security.Providers.Evernote
{
/// <summary>
/// Specifies callback methods which the <see cref="EvernoteAuthenticationMiddleware"></see> invokes to enable developer control over the authentication process. />
/// </summary>
public interface IEvernoteAuthenticationProvider
{
/// <summary>
/// Invoked whenever Evernote 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(EvernoteAuthenticatedContext 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(EvernoteReturnEndpointContext 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.Evernote {
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.Evernote.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,9 @@
namespace Owin.Security.Providers.Evernote
{
public enum SignatureTypes
{
Hmacsha1,
Plaintext,
Rsasha1
}
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CsQuery" version="1.3.4" targetFramework="net45" />
<package id="evernote-cloud-sdk-windows" version="1.0.8" targetFramework="net45" />
<package id="Microsoft.Owin" version="3.0.1" targetFramework="net452" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
<package id="PreMailer.Net" version="1.2.7" targetFramework="net45" />
<package id="SgmlReader" version="1.8.11" targetFramework="net45" />
</packages>

View File

@@ -81,9 +81,25 @@ namespace Owin.Security.Providers.PayPal
new KeyValuePair<string, string>("code", code),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
});
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
string text = "";
try
{
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
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

@@ -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>