massive change to the solution (#151)

Nice work...I'm not in love with the fact that it still has that github change in it, but I'll take it...I don't think its too dangerous.

That being said breaking these packages apart is both very helpful, and not simple so thank you for that!

I'll plan on publishing to nuget later this week after some testing...
This commit is contained in:
Eonasdan
2016-04-18 08:49:34 -04:00
committed by Tommy Parnell
parent 14905887ec
commit e1fc9e108b
737 changed files with 24555 additions and 9828 deletions

63
.gitignore vendored
View File

@@ -1,34 +1,3 @@
#################
## Eclipse
#################
*.pydevproject
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# External tool builders
.externalToolBuilders/
# Locally stored "Eclipse launch configurations"
*.launch
# CDT-specific
.cproject
# PDT-specific
.buildpath
#################
## Visual Studio
#################
@@ -188,34 +157,4 @@ $RECYCLE.BIN/
# Mac crap
.DS_Store
#############
## Python
#############
*.py[co]
# Packages
*.egg
*.egg-info
dist/
build/
eggs/
parts/
var/
sdist/
develop-eggs/
.installed.cfg
# Installer logs
pip-log.txt
# Unit test / coverage reports
.coverage
.tox
#Translations
*.mo
#Mr Developer
.mr.developer.cfg
/Output

View File

@@ -1,35 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers</id>
<version>1.27</version>
<authors>Jerrie Pelser and contributors</authors>
<owners>Jerrie Pelser</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/owin-middleware/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds additional OAuth providers for OWIN to use with ASP.NET
</description>
<summary>
Additional OAuth providers for Katana (OWIN).
Includes providers for ArcGISOnline, Asana, Backlog, Battle.net, Bitbucket, Buffer, DeviantArt, Dropbox, EVEOnline, Fitbit, Flickr, Foursquare, GitHub, Gitter, Google+, HealthGraph, Imgur, Instagram, LinkedIn, Onshape, PayPal, Reddit, Salesforce, Slack, SoundCloud, Spotify, StackExchange, TripIt, Twitch.tv, Untappd, Vimeo, Visual Studio Online, VKontakte, Wordpress, Yahoo and Yammer.
Also adds generic OpenID 2.0 providers as well implementations for Steam and Wargaming.
</summary>
<releaseNotes>
Version 1.27
- Adds Xing provider
</releaseNotes>
<copyright>Copyright 2013 - 2016</copyright>
<tags>owin katana oauth LinkedIn Yahoo Google+ GitHub Reddit Instagram StackExchange SalesForce TripIt Buffer ArcGIS Dropbox Wordpress Battle.NET Yammer OpenID Steam Twitch</tags>
<dependencies>
<dependency id="Microsoft.Owin.Security" version="2.1.0" />
<dependency id="Newtonsoft.Json" version="6.0.1" />
</dependencies>
</metadata>
<files>
<file src="..\Owin.Security.Providers\bin\Release\Owin.Security.Providers.dll" target="lib\net45" />
</files>
</package>

View File

@@ -1,239 +0,0 @@
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;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.ArcGISOnline
{
public class ArcGISOnlineAuthenticationHandler : AuthenticationHandler<ArcGISOnlineAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public ArcGISOnlineAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(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);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the ArcGISOnline user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?f=json&token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
var user = JsonConvert.DeserializeObject<Owin.Security.Providers.ArcGISOnline.Provider.ArcGISOnlineUser>(text);
var context = new ArcGISOnlineAuthenticatedContext(Context, user, accessToken);
context.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:ArcGISOnline:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:ArcGISOnline:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties=challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string 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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new ArcGISOnlineReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,16 +0,0 @@
using System;
namespace Owin.Security.Providers.ArcGISOnline.Provider
{
public class ArcGISOnlineUser
{
public User user { get; set; }
}
public class User
{
public string username { get; set; }
public string fullName { get; set; }
public string email { get; set; }
}
}

View File

@@ -1,240 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
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 Owin.Security.Providers.Backlog;
using System.Net.Http.Headers;
namespace Owin.Security.Providers.Backlog
{
public class BacklogAuthenticationHandler : AuthenticationHandler<BacklogAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public BacklogAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Get token
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);
tokenRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
tokenRequest.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(tokenRequest, Request.CallCancelled);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
string refreshToken = null;
if (response.refresh_token != null)
refreshToken = (string) response.refresh_token;
string tokenType = (string)response.token_type;
// Get the Backlog user
var userRequest = new HttpRequestMessage(HttpMethod.Get, Options.UserInfoEndpoint);
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
userRequest.Headers.Authorization = new AuthenticationHeaderValue(tokenType, Uri.EscapeDataString(accessToken));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new BacklogAuthenticatedContext(Context, user, accessToken, expires, refreshToken);
context.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));
}
if (!string.IsNullOrEmpty(context.MailAddress))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.MailAddress, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new BacklogReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,293 +0,0 @@
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;
namespace Owin.Security.Providers.BattleNet
{
public class BattleNetAuthenticationHandler : AuthenticationHandler<BattleNetAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private string tokenEndpoint = "https://eu.battle.net/oauth/token";
private string accountUserIdEndpoint = "https://eu.api.battle.net/account/user/id";
private string accountUserBattleTagEndpoint = "https://eu.api.battle.net/account/user/battletag";
private string oauthAuthEndpoint = "https://eu.battle.net/oauth/authorize";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public BattleNetAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override Task InitializeCoreAsync()
{
switch (Options.Region)
{
case Region.China:
tokenEndpoint = "https://cn.battle.net/oauth/token";
accountUserIdEndpoint = "https://cn.api.battle.net/account/user/id";
accountUserBattleTagEndpoint = "https://cn.api.battle.net/account/user/battletag";
oauthAuthEndpoint = "https://cn.battle.net/oauth/authorize";
break;
case Region.Korea:
tokenEndpoint = "https://kr.battle.net/oauth/token";
accountUserIdEndpoint = "https://kr.api.battle.net/account/user/id";
accountUserBattleTagEndpoint = "https://kr.api.battle.net/account/user/battletag";
oauthAuthEndpoint = "https://kr.battle.net/oauth/authorize";
break;
case Region.Taiwan:
tokenEndpoint = "https://tw.battle.net/oauth/token";
accountUserIdEndpoint = "https://tw.api.battle.net/account/user/id";
accountUserBattleTagEndpoint = "https://tw.api.battle.net/account/user/battletag";
oauthAuthEndpoint = "https://tw.battle.net/oauth/authorize";
break;
case Region.Europe:
tokenEndpoint = "https://eu.battle.net/oauth/token";
accountUserIdEndpoint = "https://eu.api.battle.net/account/user/id";
accountUserBattleTagEndpoint = "https://eu.api.battle.net/account/user/battletag";
oauthAuthEndpoint = "https://eu.battle.net/oauth/authorize";
break;
default:
tokenEndpoint = "https://us.battle.net/oauth/token";
accountUserIdEndpoint = "https://us.api.battle.net/account/user/id";
accountUserBattleTagEndpoint = "https://us.api.battle.net/account/user/battletag";
oauthAuthEndpoint = "https://us.battle.net/oauth/authorize";
break;
}
return Task.FromResult(true);
}
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);
}
// Check for error
if (Request.Query.Get("error") != null)
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 tokenResponse = await httpClient.PostAsync(tokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
var response = JsonConvert.DeserializeObject<dynamic>(text);
var accessToken = (string)response.access_token;
var expires = (string)response.expires_in;
// Get WoW User Id
var graphResponse = await httpClient.GetAsync(accountUserIdEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
var userId = JObject.Parse(text);
// Get WoW BattleTag
graphResponse = await httpClient.GetAsync(accountUserBattleTagEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
var battleTag = JObject.Parse(text);
var context = new BattleNetAuthenticatedContext(Context, userId, battleTag, accessToken, 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.BattleTag))
{
context.Identity.AddClaim(new Claim("urn:battlenet:battletag", context.BattleTag, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:battlenet:accesstoken", context.AccessToken, 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)
{
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;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
var scope = string.Join(" ", Options.Scope);
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
oauthAuthEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// 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 BattleNetReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,222 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Buffer
{
public class BufferAuthenticationHandler : AuthenticationHandler<BufferAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.bufferapp.com/1/oauth2/token.json";
private const string UserInfoEndpoint = "https://api.bufferapp.com/1/user.json";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public BufferAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
// Get the Buffer user
HttpResponseMessage graphResponse = await httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new BufferAuthenticatedContext(Context, user, accessToken, expires);
context.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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://bufferapp.com/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new BufferReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,345 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Claims;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Cosign.Provider;
namespace Owin.Security.Providers.Cosign
{
public class CosignAuthenticationHandler : AuthenticationHandler<CosignAuthenticationOptions>
{
/*
Cosign sends authenticated users to iis web site root (not to application).
We need redirect user back to Identity Server application.
This can be done with different approaches http handler, url rewrite...
Here is UrlRewrite configuration
<rewrite>
<rules>
<clear />
<rule name="Cosign-RedirectCore1" enabled="true" stopProcessing="true">
<match url="cosign/valid?" negate="false" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{QUERY_STRING}" pattern="core=core1" />
</conditions>
<action type="Redirect" url="https://yourserver/host/path/signin-cosign" redirectType="SeeOther" />
</rule>
<rule name="Cosign-RedirectCore2" enabled="true" stopProcessing="true">
<match url="cosign/valid?" negate="false" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="false">
<add input="{QUERY_STRING}" pattern="core=core2" />
</conditions>
<action type="Redirect" url="https://yourserver/host/path/signin-cosign" redirectType="SeeOther" />
</rule>
</rules>
</rewrite>
*/
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
public CosignAuthenticationHandler(ILogger logger)
{
this.logger = logger;
}
protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string serviceCookieValue = null;
string state = null;
/*BUG: IReadableStringCollection has a bug. Some charactes can be missed in the collection and replaces with blank space.
Example: having "x" character in QueryString will result in having " " in the collection.
I will use QueryString from Request object instead of IReadableStringCollection*/
//IReadableStringCollection query = Request.Query;
//IList<string> values = query.GetValues("cosign-" + Options.ClientServer);
//if (values != null && values.Count == 1)
//{
// serviceCookieValue = values[0];
//}
//values = query.GetValues("state");
//if (values != null && values.Count == 1)
//{
// state = values[0];
//}
string queryString = Request.QueryString.Value;
string[] values = queryString.Split(new string[] {"&"}, StringSplitOptions.RemoveEmptyEntries);
serviceCookieValue =
values.First(a => a.Contains(Options.ClientServer))
.Replace("cosign-" + Options.ClientServer + "=", "");
state =
values.First(a => a.Contains("state"))
.Replace("state=", "");
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
//// OAuth2 10.12 CSRF
//if (!ValidateCorrelationId(properties, logger))
//{
// return new AuthenticationTicket(null, properties);
//}
// Get host related information.
IPHostEntry hostEntry = Dns.GetHostEntry(Options.CosignServer);
// Loop through the AddressList to obtain the supported AddressFamily. This is to avoid
// an exception that occurs when the host IP Address is not compatible with the address family
// (typical in the IPv6 case).
foreach (IPAddress address in hostEntry.AddressList)
{
IPEndPoint ipLocalEndPoint = new IPEndPoint(address, Options.CosignServicePort);
using (TcpClient tcpClient = new TcpClient())
{
tcpClient.Connect(address, Options.CosignServicePort);
if (tcpClient.Connected)
{
logger.WriteInformation("Cosign authenticaion handler. Connected to server ip: " + address);
//read message from connected server and validate response
NetworkStream networkStream = tcpClient.GetStream();
byte[] buffer = new byte[256];
var bytesRead = networkStream.ReadAsync(buffer, 0, buffer.Length);
var receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead.Result);
//expected message: 220 2 Collaborative Web Single Sign-On [COSIGNv3 FACTORS=5 REKEY]
if (receivedData.Substring(0, 3) != "220")
continue;
//initiate secure negotiation and validate resonse
//buffer = Encoding.UTF8.GetBytes("STARTTLS 2\r\n");
buffer = Encoding.UTF8.GetBytes("STARTTLS 2" + Environment.NewLine);
networkStream.Write(buffer, 0, buffer.Length);
networkStream.Flush();
buffer = new byte[256];
bytesRead = networkStream.ReadAsync(buffer, 0, buffer.Length);
receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead.Result);
//expected message: 220 Ready to start TLS
if (receivedData.Substring(0, 3) != "220")
continue;
SslStream sslStream = new SslStream(tcpClient.GetStream(), false, ValidateServerCertificate,
null);
X509CertificateCollection certs = GetCertificateCertificateCollection(Options.ClientServer,
StoreName.My,
StoreLocation.LocalMachine);
try
{
Task authResult = sslStream.AuthenticateAsClientAsync(Options.CosignServer, certs, SslProtocols.Tls, false);
authResult.GetAwaiter().GetResult();
}
catch (AuthenticationException e)
{
logger.WriteError(e.Message);
if (e.InnerException != null)
{
logger.WriteError(string.Format("Inner exception: {0}", e.InnerException.Message));
}
logger.WriteError("Authentication failed - closing the connection.");
tcpClient.Close();
continue;
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
tcpClient.Close();
continue;
}
if (!sslStream.IsEncrypted || !sslStream.IsSigned || !sslStream.IsMutuallyAuthenticated)
continue;
// The server name must match the name on the server certificate.
if (!sslStream.IsAuthenticated)
continue;
buffer = new byte[256];
bytesRead = sslStream.ReadAsync(buffer, 0, buffer.Length);
receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead.Result);
//expected message: 220 2 Collaborative Web Single Sign-On [COSIGNv3 FACTORS=5 REKEY]
if (receivedData.Substring(0, 3) != "220")
continue;
byte[] data =
Encoding.UTF8.GetBytes("CHECK " + "cosign-" + Options.ClientServer + "=" +
serviceCookieValue + Environment.NewLine);
sslStream.Write(data, 0, data.Length);
sslStream.Flush();
buffer = new byte[256];
bytesRead = sslStream.ReadAsync(buffer, 0, buffer.Length);
receivedData = Encoding.UTF8.GetString(buffer, 0, bytesRead.Result);
switch (receivedData.Substring(0, 1))
{
case "2":
//Success
logger.WriteInformation("Cosign authenticaion handler. 2-Response from Server: Success.");
var context = new CosignAuthenticatedContext(Context, receivedData)
{
Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType)
};
var identity = new ClaimsIdentity(Options.SignInAsAuthenticationType);
if (!string.IsNullOrEmpty(context.Id))
{
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.Id,
XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserId))
{
identity.AddClaim(new Claim("UserId", context.UserId, XmlSchemaString,
Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.IpAddress))
{
identity.AddClaim(new Claim("IpAddress", context.IpAddress, XmlSchemaString,
Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Realm))
{
identity.AddClaim(new Claim("Realm", context.Realm, XmlSchemaString,
Options.AuthenticationType));
}
context.Properties = properties;
return Task.FromResult(new AuthenticationTicket(identity, properties));
case "4":
//Logged out
logger.WriteInformation("Cosign authenticaion handler. Response from Server: 4-Logged out.");
break;
case "5":
//Try a different server
logger.WriteInformation("Cosign authenticaion handler. Response from Server: 5-Try different server.");
break;
default:
logger.WriteInformation("Cosign authenticaion handler. Response from Server: Undefined.");
break;
}
}
}
}
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
}
return Task.FromResult(new AuthenticationTicket(null, properties));
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode == 401)
{
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
// Only react to 401 if there is an authentication challenge for the authentication
// type of this handler.
if (challenge != null)
{
var state = challenge.Properties;
if (string.IsNullOrEmpty(state.RedirectUri))
{
state.RedirectUri = Request.Uri.ToString();
}
var stateString = Options.StateDataFormat.Protect(state);
string loginUrl =
"https://" + Options.CosignServer + "/?cosign-" + Options.ClientServer +
"&state=" + Uri.EscapeDataString(stateString) +
"&core=" + Options.IdentityServerHostInstance;
logger.WriteInformation("Cosign authenticaion handler. Redirecting to cosign. " + loginUrl);
Response.Redirect(loginUrl);
}
}
return Task.FromResult<object>(null);
}
public override async Task<bool> InvokeAsync()
{
// This is always invoked on each request. For passive middleware, only do anything if this is
// for our callback path when the user is redirected back from the authentication provider.
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
var ticket = await AuthenticateAsync();
if (ticket != null)
{
Context.Authentication.SignIn(ticket.Properties, ticket.Identity);
Response.Redirect(ticket.Properties.RedirectUri);
// Prevent further processing by the owin pipeline.
return true;
}
}
// Let the rest of the pipeline run.
return false;
}
public static X509CertificateCollection GetCertificateCertificateCollection(string subjectName,
StoreName storeName,
StoreLocation storeLocation)
{
// The following code gets the cert from the keystore
X509Store store = new X509Store(storeName, storeLocation);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection =
store.Certificates.Find(X509FindType.FindBySubjectName,
subjectName,
false);
return certCollection;
}
private static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
return false;
}
}
}

View File

@@ -1,235 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
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 Owin.Security.Providers.DeviantArt;
using Owin.Security.Providers.DeviantArt.Provider;
namespace Owin.Security.Providers.DeviantArt
{
public class DeviantArtAuthenticationHandler : AuthenticationHandler<DeviantArtAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public DeviantArtAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = string.Copy(values.First());
}
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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Content = new FormUrlEncodedContent(body);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the DeviantArt user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new DeviantArtAuthenticatedContext(Context, user, accessToken);
context.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.Name))
{
context.Identity.AddClaim(new Claim("urn:DeviantArt:name", 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(" ", Options.Scope.Distinct());
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&response_type=" + "code" +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new DeviantArtReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,229 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Dropbox
{
public class DropboxAuthenticationHandler : AuthenticationHandler<DropboxAuthenticationOptions>
{
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 readonly ILogger logger;
private readonly HttpClient httpClient;
public DropboxAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
}
state = Request.Cookies[StateCookie];
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
// Check for error
if (Request.Query.Get("error") != null)
return new AuthenticationTicket(null, properties);
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.AppKey));
body.Add(new KeyValuePair<string, string>("client_secret", Options.AppSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the Dropbox user
HttpResponseMessage graphResponse = await httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new DropboxAuthenticatedContext(Context, user, accessToken);
context.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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string authorizationEndpoint =
"https://www.dropbox.com/1/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.AppKey) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri);
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Secure = Request.IsSecure
};
Response.StatusCode = 302;
Response.Cookies.Append(StateCookie, Options.StateDataFormat.Protect(properties), cookieOptions);
Response.Headers.Set("Location", 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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new DropboxReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,233 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.Fitbit.Provider;
namespace Owin.Security.Providers.Fitbit
{
public class FitbitAuthenticationHandler : AuthenticationHandler<FitbitAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public FitbitAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", new Base64TextEncoder().Encode(Encoding.ASCII.GetBytes(Options.ClientId + ":" + Options.ClientSecret)));
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string refreshToken = (string) response.refresh_token;
// Get the user info
var userInfoRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserEndpoint);
userInfoRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
userInfoRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userInfoResponse = await httpClient.SendAsync(userInfoRequest);
userInfoResponse.EnsureSuccessStatusCode();
text = await userInfoResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new FitbitAuthenticatedContext(Context, user, accessToken, refreshToken);
context.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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(" ", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&response_type=" + Uri.EscapeDataString("code") +
"&scope=" + Uri.EscapeDataString(scope) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&prompt=" + Uri.EscapeDataString(Options.Prompt) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new FitbitReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,237 +0,0 @@
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;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.GitHub
{
public class GitHubAuthenticationHandler : AuthenticationHandler<GitHubAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public GitHubAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(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);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the GitHub user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new GitHubAuthenticatedContext(Context, user, accessToken);
context.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:github:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:github: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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new GitHubReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,259 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
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 Owin.Security.Providers.GooglePlus.Provider;
namespace Owin.Security.Providers.GooglePlus
{
public class GooglePlusAuthenticationHandler : AuthenticationHandler<GooglePlusAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://accounts.google.com/o/oauth2/token";
private const string UserInfoEndpoint = "https://www.googleapis.com/oauth2/v3/userinfo";
private const string GooglePlusUserEndpoint = "https://www.googleapis.com/plus/v1/people/me";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public GooglePlusAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
string refreshToken = null;
if (response.refresh_token != null)
refreshToken = (string) response.refresh_token;
// Get the Google user
HttpResponseMessage graphResponse = await httpClient.GetAsync(
UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
// Get the Google+ Person Info
graphResponse = await httpClient.GetAsync(
GooglePlusUserEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken), Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject person = JObject.Parse(text);
var context = new GooglePlusAuthenticatedContext(Context, user, person, accessToken, expires, refreshToken);
context.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:googleplus:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:googleplus: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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(" ", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://accounts.google.com/o/oauth2/auth" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state);
// Check if offline access was requested
if (Options.RequestOfflineAccess)
authorizationEndpoint += "&access_type=offline";
// Request the moment types
if (Options.MomentTypes.Count > 0)
authorizationEndpoint += String.Format("&request_visible_actions={0}",
String.Join(" ", Options.MomentTypes));
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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new GooglePlusReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,234 +0,0 @@
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;
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 Owin.Security.Providers.HealthGraph.Provider;
namespace Owin.Security.Providers.HealthGraph
{
public class HealthGraphAuthenticationHandler : AuthenticationHandler<HealthGraphAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private HttpClient httpClient;
private ILogger logger;
public HealthGraphAuthenticationHandler(
HttpClient httpClient,
ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected async override Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(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);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the RunKeeper user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
var userText = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(userText);
// Get the RunKeeper Profile
HttpRequestMessage profileRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.ProfileInfoEndpoint + "?access_token=" + Uri.EscapeDataString(accessToken));
HttpResponseMessage profileResponse = await httpClient.SendAsync(profileRequest, Request.CallCancelled);
profileResponse.EnsureSuccessStatusCode();
var profileText = await profileResponse.Content.ReadAsStringAsync();
JObject profile = JObject.Parse(profileText);
var context = new HealthGraphAuthenticatedContext(Context, user, profile, accessToken);
context.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(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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&response_type=code" +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new HealthGraphReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,231 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
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 Owin.Security.Providers.Instagram.Provider;
namespace Owin.Security.Providers.Instagram
{
public class InstagramAuthenticationHandler : AuthenticationHandler<InstagramAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.instagram.com/oauth/access_token";
private readonly HttpClient httpClient;
private readonly ILogger logger;
public InstagramAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
JObject user = (JObject) response.user;
var context = new InstagramAuthenticatedContext(Context, user, accessToken);
context.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.Name))
{
context.Identity.AddClaim(new Claim("urn:instagram:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.ProfilePicture))
{
context.Identity.AddClaim(new Claim("urn:instagram:profilepicture", context.ProfilePicture, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:instagram:accesstoken", context.AccessToken, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// plus separated (do not URL encode)
string scope = string.Join("+", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://api.instagram.com/oauth/authorize/" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + 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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new InstagramReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,258 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
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 UserInfoEndpoint = "https://api.linkedin.com/v1/people/";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public LinkedInAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
// Get the LinkedIn user
string userInfoEndpoint = UserInfoEndpoint
+ "~:("+ string.Join(",", Options.ProfileFields.Distinct().ToArray()) +")"
+ "?oauth2_access_token=" + Uri.EscapeDataString(accessToken);
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, userInfoEndpoint);
userRequest.Headers.Add("x-li-format", "json");
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new LinkedInAuthenticatedContext(Context, user, accessToken, expires);
context.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.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.GivenName))
{
context.Identity.AddClaim(new Claim(ClaimTypes.GivenName, context.GivenName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.FamilyName))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Surname, context.FamilyName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Name))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Name, XmlSchemaString, Options.AuthenticationType));
context.Identity.AddClaim(new Claim("urn:linkedin:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:linkedin:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:linkedin:accesstoken", context.AccessToken, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
// allow scopes to be specified via the authentication properties for this request, when specified they will already be comma separated
if (properties.Dictionary.ContainsKey("scope"))
{
scope = properties.Dictionary["scope"];
}
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://www.linkedin.com/uas/oauth2/authorization" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new LinkedInReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,246 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http.Headers;
namespace Owin.Security.Providers.Onshape
{
public class OnshapeAuthenticationHandler : AuthenticationHandler<OnshapeAuthenticationOptions>
{
private const string StateCookie = "_OnshapeState";
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string AuthorizationEndpoint = "/oauth/authorize";
private const string TokenEndpoint = "/oauth/token";
private const string UserInfoEndpoint = "/api/users/session";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public OnshapeAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
// Check for error
if (Request.Query.Get("error") != null)
return new AuthenticationTicket(null, properties);
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.AppKey));
body.Add(new KeyValuePair<string, string>("client_secret", Options.AppSecret));
// Get token
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, "https://" + Options.Hostname + TokenEndpoint);
tokenRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
tokenRequest.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(tokenRequest, Request.CallCancelled);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string tokenType = (string)response.token_type;
var userRequest = new HttpRequestMessage(HttpMethod.Get, "https://" + Options.Hostname + UserInfoEndpoint);
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
userRequest.Headers.Authorization = new AuthenticationHeaderValue(tokenType, accessToken);
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new OnshapeAuthenticatedContext(Context, user, accessToken);
context.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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://" + Options.Hostname + AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.AppKey) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
var cookieOptions = new CookieOptions
{
HttpOnly = true,
Secure = Request.IsSecure
};
Response.StatusCode = 302;
Response.Headers.Set("Location", 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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new OnshapeReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,8 +0,0 @@

namespace Owin.Security.Providers.OpenID
{
internal static class Constants
{
internal const string DefaultAuthenticationType = "OpenID";
}
}

View File

@@ -1,116 +0,0 @@
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;
using Owin.Security.Providers.Properties;
using System;
using System.Globalization;
using System.Net.Http;
namespace Owin.Security.Providers.OpenID
{
/// <summary>
/// OWIN middleware for authenticating users using an OpenID provider
/// </summary>
public class OpenIDAuthenticationMiddleware : OpenIDAuthenticationMiddlewareBase<OpenIDAuthenticationOptions>
{
/// <summary>
/// Initializes a <see cref="OpenIDAuthenticationMiddleware"/>
/// </summary>
/// <param name="next">The next middleware in the OWIN pipeline to invoke</param>
/// <param name="app">The OWIN application</param>
/// <param name="options">Configuration options for the middleware</param>
public OpenIDAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app, OpenIDAuthenticationOptions options)
: base(next, app, options)
{ }
protected override AuthenticationHandler<OpenIDAuthenticationOptions> CreateSpecificHandler()
{
return new OpenIDAuthenticationHandler(_httpClient, _logger);
}
}
/// <summary>
/// OWIN middleware for authenticating users using an OpenID provider
/// </summary>
public abstract class OpenIDAuthenticationMiddlewareBase<T> : AuthenticationMiddleware<T> where T : OpenIDAuthenticationOptions
{
protected readonly ILogger _logger;
protected readonly HttpClient _httpClient;
/// <summary>
/// Initializes a <see cref="OpenIDAuthenticationMiddlewareBase"/>
/// </summary>
/// <param name="next">The next middleware in the OWIN pipeline to invoke</param>
/// <param name="app">The OWIN application</param>
/// <param name="options">Configuration options for the middleware</param>
public OpenIDAuthenticationMiddlewareBase(OwinMiddleware next, IAppBuilder app, T options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ProviderDiscoveryUri) && String.IsNullOrWhiteSpace(Options.ProviderLoginUri) && Options.AuthenticationType != Constants.DefaultAuthenticationType)
{
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "ProviderDiscoveryUri"));
}
_logger = app.CreateLogger<OpenIDAuthenticationMiddleware>();
if (Options.Provider == null)
{
Options.Provider = new OpenIDAuthenticationProvider();
}
if (Options.StateDataFormat == null)
{
IDataProtector dataProtecter = app.CreateDataProtector(
typeof(OpenIDAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtecter);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
{
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
}
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options));
_httpClient.Timeout = Options.BackchannelTimeout;
_httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
}
/// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIDAuthenticationOptions"/> supplied to the constructor.</returns>
protected override AuthenticationHandler<T> CreateHandler()
{
return CreateSpecificHandler();
}
/// <summary>
/// Provides the <see cref="AuthenticationHandler"/> object for processing authentication-related requests.
/// </summary>
/// <returns>An <see cref="AuthenticationHandler"/> configured with the <see cref="OpenIDAuthenticationOptions"/> supplied to the constructor.</returns>
protected abstract AuthenticationHandler<T> CreateSpecificHandler();
private static HttpMessageHandler ResolveHttpMessageHandler(OpenIDAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
{
// 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

@@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Owin.Security.Providers.OpenID
{
public class OpenIDAuthorizationEndpointInfo
{
public string Url { get; set; }
}
}

View File

@@ -1,491 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.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>{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers</RootNamespace>
<AssemblyName>Owin.Security.Providers</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>cbdbae43</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</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=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<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.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationExtensions.cs" />
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationHandler.cs" />
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationMiddleware.cs" />
<Compile Include="ArcGISOnline\ArcGISOnlineAuthenticationOptions.cs" />
<Compile Include="ArcGISOnline\Constants.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineAuthenticatedContext.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineReturnEndpointContext.cs" />
<Compile Include="ArcGISOnline\Provider\ArcGISOnlineUser.cs" />
<Compile Include="ArcGISOnline\Provider\IArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="Asana\AsanaAuthenticationExtensions.cs" />
<Compile Include="Asana\AsanaAuthenticationHandler.cs" />
<Compile Include="Asana\AsanaAuthenticationMiddleware.cs" />
<Compile Include="Asana\AsanaAuthenticationOptions.cs" />
<Compile Include="Asana\Constants.cs" />
<Compile Include="Asana\Provider\AsanaAuthenticatedContext.cs" />
<Compile Include="Asana\Provider\AsanaAuthenticationProvider.cs" />
<Compile Include="Asana\Provider\AsanaReturnEndpointContext.cs" />
<Compile Include="Asana\Provider\IAsanaAuthenticationProvider.cs" />
<Compile Include="Backlog\BacklogAuthenticationExtensions.cs" />
<Compile Include="Backlog\BacklogAuthenticationHandler.cs" />
<Compile Include="Backlog\BacklogAuthenticationMiddleware.cs" />
<Compile Include="Backlog\BacklogAuthenticationOptions.cs" />
<Compile Include="Backlog\Constants.cs" />
<Compile Include="Backlog\Provider\BacklogAuthenticatedContext.cs" />
<Compile Include="Backlog\Provider\BacklogAuthenticationProvider.cs" />
<Compile Include="Backlog\Provider\BacklogReturnEndpointContext.cs" />
<Compile Include="Backlog\Provider\IGBacklogAuthenticationProvider.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationExtensions.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationHandler.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationMiddleware.cs" />
<Compile Include="BattleNet\BattleNetAuthenticationOptions.cs" />
<Compile Include="BattleNet\Provider\BattleNetAuthenticatedContext.cs" />
<Compile Include="BattleNet\Provider\BattleNetAuthenticationProvider.cs" />
<Compile Include="BattleNet\Provider\BattleNetReturnEndpointContext.cs" />
<Compile Include="BattleNet\Provider\IBattleNetAuthenticationProvider.cs" />
<Compile Include="Buffer\BufferAuthenticationExtensions.cs" />
<Compile Include="Buffer\BufferAuthenticationHandler.cs" />
<Compile Include="Buffer\BufferAuthenticationMiddleware.cs" />
<Compile Include="Buffer\BufferAuthenticationOptions.cs" />
<Compile Include="Buffer\Constants.cs" />
<Compile Include="Buffer\Provider\BufferAuthenticatedContext.cs" />
<Compile Include="Buffer\Provider\BufferAuthenticationProvider.cs" />
<Compile Include="Buffer\Provider\BufferReturnEndpointContext.cs" />
<Compile Include="Buffer\Provider\IBufferAuthenticationProvider.cs" />
<Compile Include="BattleNet\Constants.cs" />
<Compile Include="DeviantArt\Constants.cs" />
<Compile Include="DeviantArt\Provider\IDeviantAuthenticationProvider.cs" />
<Compile Include="DeviantArt\Provider\DeviantAuthenticatedContext.cs" />
<Compile Include="DeviantArt\Provider\DeviantAuthenticationProvider.cs" />
<Compile Include="DeviantArt\Provider\DeviantReturnEndpointContext.cs" />
<Compile Include="DeviantArt\DeviantAuthenticationExtensions.cs" />
<Compile Include="DeviantArt\DeviantAuthenticationHandler.cs" />
<Compile Include="DeviantArt\DeviantAuthenticationMiddleware.cs" />
<Compile Include="DeviantArt\DeviantAuthenticationOptions.cs" />
<Compile Include="DoYouBuzz\Constants.cs" />
<Compile Include="DoYouBuzz\DoYouBuzzAuthenticationHandler.cs" />
<Compile Include="DoYouBuzz\DoYouBuzzAuthenticationMiddleware.cs" />
<Compile Include="DoYouBuzz\DoYouBuzzAuthenticationOptions.cs" />
<Compile Include="DoYouBuzz\Messages\AccessToken.cs" />
<Compile Include="DoYouBuzz\Messages\RequestToken.cs" />
<Compile Include="DoYouBuzz\Messages\RequestTokenSerializer.cs" />
<Compile Include="DoYouBuzz\Messages\Resume.cs" />
<Compile Include="DoYouBuzz\Messages\Serializer.cs" />
<Compile Include="DoYouBuzz\Messages\UserInfo.cs" />
<Compile Include="DoYouBuzz\Provider\DoYouBuzzApplyRedirectContext.cs" />
<Compile Include="DoYouBuzz\Provider\DoYouBuzzAuthenticatedContext.cs" />
<Compile Include="DoYouBuzz\Provider\DoYouBuzzAuthenticationProvider.cs" />
<Compile Include="DoYouBuzz\Provider\DoYouBuzzReturnEndpointContext.cs" />
<Compile Include="DoYouBuzz\Provider\IDoYouBuzzAuthenticationProvider.cs" />
<Compile Include="DoYouBuzz\DoYouBuzzAuthenticationExtensions.cs" />
<Compile Include="Dropbox\DropboxAuthenticationExtensions.cs" />
<Compile Include="Dropbox\DropboxAuthenticationHandler.cs" />
<Compile Include="Dropbox\DropboxAuthenticationMiddleware.cs" />
<Compile Include="Dropbox\DropboxAuthenticationOptions.cs" />
<Compile Include="Dropbox\Constants.cs" />
<Compile Include="Dropbox\Provider\DropboxAuthenticatedContext.cs" />
<Compile Include="Dropbox\Provider\DropboxAuthenticationProvider.cs" />
<Compile Include="Dropbox\Provider\DropboxReturnEndpointContext.cs" />
<Compile Include="Dropbox\Provider\IDropboxAuthenticationProvider.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationExtensions.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationHandler.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationMiddleware.cs" />
<Compile Include="EveOnline\EveOnlineAuthenticationOptions.cs" />
<Compile Include="EveOnline\Constants.cs" />
<Compile Include="EveOnline\Provider\EveOnlineAuthenticatedContext.cs" />
<Compile Include="EveOnline\Provider\EveOnlineAuthenticationProvider.cs" />
<Compile Include="EveOnline\Provider\EveOnlineReturnEndpointContext.cs" />
<Compile Include="EveOnline\Provider\IEveOnlineAuthenticationProvider.cs" />
<Compile Include="Flickr\Constants.cs" />
<Compile Include="Flickr\FlickrAuthenticationOptions.cs" />
<Compile Include="Flickr\FlickrAuthenticationExtensions.cs" />
<Compile Include="Flickr\FlickrAuthenticationHandler.cs" />
<Compile Include="Flickr\FlickrAuthenticationMiddleware.cs" />
<Compile Include="Flickr\Messages\AccessToken.cs" />
<Compile Include="Flickr\Messages\RequestToken.cs" />
<Compile Include="Flickr\Messages\RequestTokenSerializer.cs" />
<Compile Include="Flickr\Messages\Serializers.cs" />
<Compile Include="Flickr\Provider\FlickrAuthenticatedContext.cs" />
<Compile Include="Flickr\Provider\FlickrAuthenticationProvider.cs" />
<Compile Include="Flickr\Provider\IFlickrAuthenticationProvider.cs" />
<Compile Include="Flickr\Provider\FlickrReturnEndpointContext.cs" />
<Compile Include="Foursquare\Constants.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationExtensions.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationHandler.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationMiddleware.cs" />
<Compile Include="Foursquare\FoursquareAuthenticationOptions.cs" />
<Compile Include="Foursquare\Provider\FoursquareAuthenticatedContext.cs" />
<Compile Include="Foursquare\Provider\FoursquareAuthenticationProvider.cs" />
<Compile Include="Foursquare\Provider\FoursquareReturnEndpointContext.cs" />
<Compile Include="Foursquare\Provider\IFoursquareAuthenticationProvider.cs" />
<Compile Include="Fitbit\Constants.cs" />
<Compile Include="Fitbit\FitbitAuthenticationExtensions.cs" />
<Compile Include="Fitbit\FitbitAuthenticationHandler.cs" />
<Compile Include="Fitbit\FitbitAuthenticationMiddleware.cs" />
<Compile Include="Fitbit\FitbitAuthenticationOptions.cs" />
<Compile Include="Fitbit\Provider\FitbitAuthenticatedContext.cs" />
<Compile Include="Fitbit\Provider\FitbitAuthenticationProvider.cs" />
<Compile Include="Fitbit\Provider\FitbitReturnEndpointContext.cs" />
<Compile Include="Fitbit\Provider\IFitbitAuthenticationProvider.cs" />
<Compile Include="Bitbucket\Constants.cs" />
<Compile Include="Bitbucket\BitbucketAuthenticationExtensions.cs" />
<Compile Include="Bitbucket\BitbucketAuthenticationHandler.cs" />
<Compile Include="Bitbucket\BitbucketAuthenticationMiddleware.cs" />
<Compile Include="Bitbucket\BitbucketAuthenticationOptions.cs" />
<Compile Include="Bitbucket\Provider\BitbucketAuthenticatedContext.cs" />
<Compile Include="Bitbucket\Provider\BitbucketAuthenticationProvider.cs" />
<Compile Include="Bitbucket\Provider\BitbucketReturnEndpointContext.cs" />
<Compile Include="Bitbucket\Provider\IBitbucketAuthenticationProvider.cs" />
<Compile Include="GitHub\Constants.cs" />
<Compile Include="Gitter\Constants.cs" />
<Compile Include="Gitter\GitterAuthenticationExtensions.cs" />
<Compile Include="Gitter\GitterAuthenticationHandler.cs" />
<Compile Include="Gitter\GitterAuthenticationMiddleware.cs" />
<Compile Include="Gitter\GitterAuthenticationOptions.cs" />
<Compile Include="Gitter\Provider\GitterAuthenticatedContext.cs" />
<Compile Include="Gitter\Provider\GitterAuthenticationProvider.cs" />
<Compile Include="Gitter\Provider\GitterReturnEndpointContext.cs" />
<Compile Include="Gitter\Provider\IGitterAuthenticationProvider.cs" />
<Compile Include="HealthGraph\Constants.cs" />
<Compile Include="GitHub\GitHubAuthenticationExtensions.cs" />
<Compile Include="GitHub\GitHubAuthenticationHandler.cs" />
<Compile Include="GitHub\GitHubAuthenticationMiddleware.cs" />
<Compile Include="GitHub\GitHubAuthenticationOptions.cs" />
<Compile Include="GitHub\Provider\IGitHubAuthenticationProvider.cs" />
<Compile Include="GitHub\Provider\GitHubAuthenticatedContext.cs" />
<Compile Include="GitHub\Provider\GitHubAuthenticationProvider.cs" />
<Compile Include="GitHub\Provider\GitHubReturnEndpointContext.cs" />
<Compile Include="GooglePlus\Constants.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationExtensions.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationHandler.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationMiddleware.cs" />
<Compile Include="GooglePlus\GooglePlusAuthenticationOptions.cs" />
<Compile Include="GooglePlus\Provider\GooglePlusAuthenticatedContext.cs" />
<Compile Include="GooglePlus\Provider\GooglePlusAuthenticationProvider.cs" />
<Compile Include="GooglePlus\Provider\GooglePlusReturnEndpointContext.cs" />
<Compile Include="GooglePlus\Provider\IGooglePlusAuthenticationProvider.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationExtensions.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationHandler.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationMiddleware.cs" />
<Compile Include="HealthGraph\Provider\HealthGraphAuthenticatedContext.cs" />
<Compile Include="HealthGraph\Provider\HealthGraphAuthenticationProvider.cs" />
<Compile Include="HealthGraph\Provider\HealthGraphReturnEndpointContext.cs" />
<Compile Include="HealthGraph\Provider\IHealthGraphAuthenticationProvider.cs" />
<Compile Include="Imgur\ImgurAuthenticationDefaults.cs" />
<Compile Include="Imgur\ImgurAuthenticationExtensions.cs" />
<Compile Include="Imgur\ImgurAuthenticationHandler.cs" />
<Compile Include="Imgur\ImgurAuthenticationMiddleware.cs" />
<Compile Include="Imgur\ImgurAuthenticationOptions.cs" />
<Compile Include="Imgur\Provider\IImgurAuthenticationProvider.cs" />
<Compile Include="Imgur\Provider\ImgurAuthenticationProvider.cs" />
<Compile Include="Imgur\Provider\ImgurReturnEndpointContext.cs" />
<Compile Include="Imgur\Provider\ImgurAuthenticatedContext.cs" />
<Compile Include="Instagram\Constants.cs" />
<Compile Include="Instagram\InstagramAuthenticationExtensions.cs" />
<Compile Include="Instagram\InstagramAuthenticationHandler.cs" />
<Compile Include="Instagram\InstagramAuthenticationMiddleware.cs" />
<Compile Include="Instagram\InstagramAuthenticationOptions.cs" />
<Compile Include="Instagram\Provider\IInstagramAuthenticationProvider.cs" />
<Compile Include="Instagram\Provider\InstagramAuthenticatedContext.cs" />
<Compile Include="Instagram\Provider\InstagramAuthenticationProvider.cs" />
<Compile Include="Instagram\Provider\InstagramReturnEndpointContext.cs" />
<Compile Include="LinkedIn\Constants.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationExtensions.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationHandler.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationMiddleware.cs" />
<Compile Include="LinkedIn\LinkedInAuthenticationOptions.cs" />
<Compile Include="LinkedIn\Provider\LinkedInAuthenticatedContext.cs" />
<Compile Include="LinkedIn\Provider\LinkedInAuthenticationProvider.cs" />
<Compile Include="LinkedIn\Provider\LinkedInReturnEndpointContext.cs" />
<Compile Include="LinkedIn\Provider\ILinkedInAuthenticationProvider.cs" />
<Compile Include="Onshape\Constants.cs" />
<Compile Include="Onshape\OnshapeAuthenticationExtensions.cs" />
<Compile Include="Onshape\OnshapeAuthenticationHandler.cs" />
<Compile Include="Onshape\OnshapeAuthenticationMiddleware.cs" />
<Compile Include="Onshape\OnshapeAuthenticationOptions.cs" />
<Compile Include="Onshape\Provider\IOnshapeAuthenticationProvider.cs" />
<Compile Include="Onshape\Provider\OnshapeAuthenticatedContext.cs" />
<Compile Include="Onshape\Provider\OnshapeAuthenticationProvider.cs" />
<Compile Include="Onshape\Provider\OnshapeReturnEndpointContext.cs" />
<Compile Include="OpenID\Constants.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationAuthenticationContextExtensions.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationExtension.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationResult.cs" />
<Compile Include="OpenID\Extensions\OpenIDSimpleRegistrationField.cs" />
<Compile Include="OpenID\Infrastructure\Message.cs" />
<Compile Include="OpenID\Infrastructure\Property.cs" />
<Compile Include="OpenID\IOpenIDProtocolExtension.cs" />
<Compile Include="OpenID\OpenIDAuthenticationExtensions.cs" />
<Compile Include="OpenID\OpenIDAuthenticationHandler.cs" />
<Compile Include="OpenID\OpenIDAuthenticationMiddleware.cs" />
<Compile Include="OpenID\OpenIDAuthenticationOptions.cs" />
<Compile Include="OpenID\OpenIDAuthorizationEndpointInfo.cs" />
<Compile Include="OpenID\Provider\IOpenIDAuthenticationProvider.cs" />
<Compile Include="OpenID\Provider\OpenIDAuthenticatedContext.cs" />
<Compile Include="OpenID\Provider\OpenIDAuthenticationProvider.cs" />
<Compile Include="OpenID\Provider\OpenIDReturnEndpointContext.cs" />
<Compile Include="PayPal\Constants.cs" />
<Compile Include="PayPal\PayPalAuthenticationExtensions.cs" />
<Compile Include="PayPal\PayPalAuthenticationHandler.cs" />
<Compile Include="PayPal\PayPalAuthenticationMiddleware.cs" />
<Compile Include="PayPal\PayPalAuthenticationOptions.cs" />
<Compile Include="PayPal\Provider\IPayPalAuthenticationProvider.cs" />
<Compile Include="PayPal\Provider\PayPalAuthenticatedContext.cs" />
<Compile Include="PayPal\Provider\PayPalAuthenticationProvider.cs" />
<Compile Include="PayPal\Provider\PayPalReturnEndpointContext.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Reddit\Constants.cs" />
<Compile Include="Reddit\Provider\IRedditAuthenticationProvider.cs" />
<Compile Include="Reddit\Provider\RedditAuthenticatedContext.cs" />
<Compile Include="Reddit\Provider\RedditAuthenticationProvider.cs" />
<Compile Include="Reddit\Provider\RedditReturnEndpointContext.cs" />
<Compile Include="Reddit\RedditAuthenticationExtensions.cs" />
<Compile Include="Reddit\RedditAuthenticationHandler.cs" />
<Compile Include="Reddit\RedditAuthenticationMiddleware.cs" />
<Compile Include="Reddit\RedditAuthenticationOptions.cs" />
<Compile Include="HealthGraph\HealthGraphAuthenticationOptions.cs" />
<Compile Include="Salesforce\Constants.cs" />
<Compile Include="Salesforce\Provider\ISalesforceAuthenticationProvider.cs" />
<Compile Include="Salesforce\Provider\SalesforceAuthenticatedContext.cs" />
<Compile Include="Salesforce\Provider\SalesforceAuthenticationProvider.cs" />
<Compile Include="Salesforce\Provider\SalesforceReturnEndpointContext.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationExtensions.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationHandler.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationMiddleware.cs" />
<Compile Include="Salesforce\SalesforceAuthenticationOptions.cs" />
<Compile Include="Shopify\Constants.cs" />
<Compile Include="Shopify\Provider\IShopifyAuthenticationProvider.cs" />
<Compile Include="Shopify\Provider\ShopifyAuthenticatedContext.cs" />
<Compile Include="Shopify\Provider\ShopifyAuthenticationProvider.cs" />
<Compile Include="Shopify\Provider\ShopifyReturnEndpointContext.cs" />
<Compile Include="Shopify\ShopifyAuthenticationExtensions.cs" />
<Compile Include="Shopify\ShopifyAuthenticationHandler.cs" />
<Compile Include="Shopify\ShopifyAuthenticationMiddleware.cs" />
<Compile Include="Shopify\ShopifyAuthenticationOptions.cs" />
<Compile Include="Slack\Constants.cs" />
<Compile Include="Slack\Provider\ISlackAuthenticationProvider.cs" />
<Compile Include="Slack\Provider\SlackAuthenticatedContext.cs" />
<Compile Include="Slack\Provider\SlackAuthenticationProvider.cs" />
<Compile Include="Slack\Provider\SlackReturnEndpointContext.cs" />
<Compile Include="Slack\SlackAuthenticationExtensions.cs" />
<Compile Include="Slack\SlackAuthenticationHandler.cs" />
<Compile Include="Slack\SlackAuthenticationMiddleware.cs" />
<Compile Include="Slack\SlackAuthenticationOptions.cs" />
<Compile Include="SoundCloud\Constants.cs" />
<Compile Include="SoundCloud\Provider\ISoundCloudAuthenticationProvider.cs" />
<Compile Include="SoundCloud\Provider\SoundCloudAuthenticatedContext.cs" />
<Compile Include="SoundCloud\Provider\SoundCloudAuthenticationProvider.cs" />
<Compile Include="SoundCloud\Provider\SoundCloudReturnEndpointContext.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationExtensions.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationHandler.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationMiddleware.cs" />
<Compile Include="SoundCloud\SoundCloudAuthenticationOptions.cs" />
<Compile Include="Spotify\Constants.cs" />
<Compile Include="Spotify\Provider\ISpotifyAuthenticationProvider.cs" />
<Compile Include="Spotify\Provider\SpotifyAuthenticatedContext.cs" />
<Compile Include="Spotify\Provider\SpotifyAuthenticationProvider.cs" />
<Compile Include="Spotify\Provider\SpotifyReturnEndpointContext.cs" />
<Compile Include="Spotify\SpotifyAuthenticationExtensions.cs" />
<Compile Include="Spotify\SpotifyAuthenticationHandler.cs" />
<Compile Include="Spotify\SpotifyAuthenticationMiddleware.cs" />
<Compile Include="Spotify\SpotifyAuthenticationOptions.cs" />
<Compile Include="StackExchange\Constants.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationExtensions.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationHandler.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationMiddleware.cs" />
<Compile Include="StackExchange\StackExchangeAuthenticationOptions.cs" />
<Compile Include="StackExchange\Provider\IStackExchangeAuthenticationProvider.cs" />
<Compile Include="StackExchange\Provider\StackExchangeAuthenticatedContext.cs" />
<Compile Include="StackExchange\Provider\StackExchangeAuthenticationProvider.cs" />
<Compile Include="StackExchange\Provider\StackExchangeReturnEndpointContext.cs" />
<Compile Include="Steam\SteamAuthenticationExtensions.cs" />
<Compile Include="Steam\SteamAuthenticationHandler.cs" />
<Compile Include="Steam\SteamAuthenticationMiddleware.cs" />
<Compile Include="Steam\SteamAuthenticationOptions.cs" />
<Compile Include="TripIt\Constants.cs" />
<Compile Include="TripIt\Messages\AccessToken.cs" />
<Compile Include="TripIt\Messages\RequestToken.cs" />
<Compile Include="TripIt\Messages\RequestTokenSerializer.cs" />
<Compile Include="TripIt\Messages\Serializers.cs" />
<Compile Include="TripIt\Provider\ITripItAuthenticationProvider.cs" />
<Compile Include="TripIt\Provider\TripItAuthenticatedContext.cs" />
<Compile Include="TripIt\Provider\TripItAuthenticationProvider.cs" />
<Compile Include="TripIt\Provider\TripItReturnEndpointContext.cs" />
<Compile Include="TripIt\TripItAuthenticationExtensions.cs" />
<Compile Include="TripIt\TripItAuthenticationHandler.cs" />
<Compile Include="TripIt\TripItAuthenticationMiddleware.cs" />
<Compile Include="TripIt\TripItAuthenticationOptions.cs" />
<Compile Include="Twitch\Constants.cs" />
<Compile Include="Twitch\TwitchAuthenticationExtensions.cs" />
<Compile Include="Twitch\TwitchAuthenticationHandler.cs" />
<Compile Include="Twitch\TwitchAuthenticationMiddleware.cs" />
<Compile Include="Twitch\TwitchAuthenticationOptions.cs" />
<Compile Include="Twitch\Provider\TwitchAuthenticatedContext.cs" />
<Compile Include="Twitch\Provider\TwitchAuthenticationProvider.cs" />
<Compile Include="Twitch\Provider\TwitchReturnEndpointContext.cs" />
<Compile Include="Twitch\Provider\ITwitchAuthenticationProvider.cs" />
<Compile Include="Vimeo\Constants.cs" />
<Compile Include="Vimeo\Provider\IVimeoAuthenticationProvider.cs" />
<Compile Include="Vimeo\Provider\VimeoAuthenticatedContext.cs" />
<Compile Include="Vimeo\Provider\VimeoAuthenticationProvider.cs" />
<Compile Include="Vimeo\Provider\VimeoReturnEndpointContext.cs" />
<Compile Include="Vimeo\VimeoAuthenticationExtensions.cs" />
<Compile Include="Vimeo\VimeoAuthenticationHandler.cs" />
<Compile Include="Vimeo\VimeoAuthenticationMiddleware.cs" />
<Compile Include="Vimeo\VimeoAuthenticationOptions.cs" />
<Compile Include="VisualStudio\Constants.cs" />
<Compile Include="VisualStudio\Provider\IVisualStudioAuthenticationProvider.cs" />
<Compile Include="VisualStudio\Provider\VisualStudioAuthenticatedContext.cs" />
<Compile Include="VisualStudio\Provider\VisualStudioAuthenticationProvider.cs" />
<Compile Include="VisualStudio\Provider\VisualStudioReturnEndpointContext.cs" />
<Compile Include="VisualStudio\VisualStudioAuthenticationExtensions.cs" />
<Compile Include="VisualStudio\VisualStudioAuthenticationHandler.cs" />
<Compile Include="VisualStudio\VisualStudioAuthenticationMiddleware.cs" />
<Compile Include="VisualStudio\VisualStudioAuthenticationOptions.cs" />
<Compile Include="Untappd\ApiResponse.cs" />
<Compile Include="VKontakte\Constants.cs" />
<Compile Include="VKontakte\VKontakteAuthenticationEndpoints.cs" />
<Compile Include="VKontakte\VKontakteAuthenticationExtensions.cs" />
<Compile Include="VKontakte\VKontakteAuthenticationHandler.cs" />
<Compile Include="VKontakte\VKontakteAuthenticationMiddleware.cs" />
<Compile Include="VKontakte\VKontakteAuthenticationOptions.cs" />
<Compile Include="VKontakte\Provider\VKontakteAuthenticatedContext.cs" />
<Compile Include="VKontakte\Provider\VKontakteAuthenticationProvider.cs" />
<Compile Include="VKontakte\Provider\VKontakteReturnEndpointContext.cs" />
<Compile Include="VKontakte\Provider\IVKontakteAuthenticationProvider.cs" />
<Compile Include="Wargaming\Constants.cs" />
<Compile Include="Wargaming\WargamingAccountAuthenticationExtensions.cs" />
<Compile Include="Wargaming\WargamingAuthenticationHandler.cs" />
<Compile Include="Wargaming\WargamingAuthenticationOptions.cs" />
<Compile Include="Wargaming\WargamingAuthenticationMiddleware.cs" />
<Compile Include="Untappd\Constants.cs" />
<Compile Include="Untappd\Provider\IUntappdAuthenticationProvider.cs" />
<Compile Include="Untappd\Provider\UntappdAuthenticatedContext.cs" />
<Compile Include="Untappd\Provider\UntappdAuthenticationProvider.cs" />
<Compile Include="Untappd\Provider\UntappdReturnEndpointContext.cs" />
<Compile Include="Untappd\UntappdAuthenticationExtensions.cs" />
<Compile Include="Untappd\UntappdAuthenticationHandler.cs" />
<Compile Include="Untappd\UntappdAuthenticationMiddleware.cs" />
<Compile Include="Untappd\UntappdAuthenticationOptions.cs" />
<Compile Include="WordPress\WordPressAuthenticationExtensions.cs" />
<Compile Include="WordPress\WordPressAuthenticationHandler.cs" />
<Compile Include="WordPress\WordPressAuthenticationMiddleware.cs" />
<Compile Include="WordPress\WordPressAuthenticationOptions.cs" />
<Compile Include="WordPress\Constants.cs" />
<Compile Include="WordPress\Provider\WordPressAuthenticatedContext.cs" />
<Compile Include="WordPress\Provider\WordPressAuthenticationProvider.cs" />
<Compile Include="WordPress\Provider\WordPressReturnEndpointContext.cs" />
<Compile Include="WordPress\Provider\IWordPressAuthenticationProvider.cs" />
<Compile Include="Xing\Constants.cs" />
<Compile Include="Xing\Messages\AccessToken.cs" />
<Compile Include="Xing\Messages\RequestToken.cs" />
<Compile Include="Xing\Messages\RequestTokenSerializer.cs" />
<Compile Include="Xing\Messages\Serializer.cs" />
<Compile Include="Xing\Provider\IXingAuthenticationProvider.cs" />
<Compile Include="Xing\Provider\XingApplyRedirectContext.cs" />
<Compile Include="Xing\Provider\XingAuthenticatedContext.cs" />
<Compile Include="Xing\Provider\XingAuthenticationProvider.cs" />
<Compile Include="Xing\Provider\XingReturnEndpointContext.cs" />
<Compile Include="Xing\XingAuthenticationExtensions.cs" />
<Compile Include="Xing\XingAuthenticationHandler.cs" />
<Compile Include="Xing\XingAuthenticationMiddleware.cs" />
<Compile Include="Xing\XingAuthenticationOptions.cs" />
<Compile Include="Yahoo\Constants.cs" />
<Compile Include="Yahoo\Messages\AccessToken.cs" />
<Compile Include="Yahoo\Messages\RequestToken.cs" />
<Compile Include="Yahoo\Messages\RequestTokenSerializer.cs" />
<Compile Include="Yahoo\Messages\Serializers.cs" />
<Compile Include="Yahoo\Provider\IYahooAuthenticationProvider.cs" />
<Compile Include="Yahoo\Provider\YahooAuthenticatedContext.cs" />
<Compile Include="Yahoo\Provider\YahooAuthenticationProvider.cs" />
<Compile Include="Yahoo\Provider\YahooReturnEndpointContext.cs" />
<Compile Include="Yahoo\YahooAuthenticationExtensions.cs" />
<Compile Include="Yahoo\YahooAuthenticationHandler.cs" />
<Compile Include="Yahoo\YahooAuthenticationMiddleware.cs" />
<Compile Include="Yahoo\YahooAuthenticationOptions.cs" />
<Compile Include="Yammer\Constants.cs" />
<Compile Include="Yammer\Provider\IYammerAuthenticationProvider.cs" />
<Compile Include="Yammer\Provider\YammerAuthenticatedContext.cs" />
<Compile Include="Yammer\Provider\YammerAuthenticationProvider.cs" />
<Compile Include="Yammer\Provider\YammerReturnEndpointContext.cs" />
<Compile Include="Yammer\YammerAuthenticationHandler.cs" />
<Compile Include="Yammer\YammerAuthenticationExtensions.cs" />
<Compile Include="Yammer\YammerAuthenticationMiddleware.cs" />
<Compile Include="Yammer\YammerAuthenticationOptions.cs" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<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

@@ -1,7 +0,0 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=BattleNet_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Buffer_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=DropBox_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=Dropbox_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=GitHub_005CProvider/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=WordPress_005CProvider/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -1,36 +0,0 @@
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")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[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("c745499f-213a-461d-9dfb-c46935ec44e9")]
// 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.25.0.0")]
[assembly: AssemblyFileVersion("1.25.0.0")]

View File

@@ -1,246 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
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 Owin.Security.Providers.Reddit.Provider;
namespace Owin.Security.Providers.Reddit
{
public class RedditAuthenticationHandler : AuthenticationHandler<RedditAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://ssl.reddit.com/api/v1/access_token";
private const string UserInfoEndpoint = "https://oauth.reddit.com/api/v1/me";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public RedditAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("state", state));
body.Add(new KeyValuePair<string, string>("scope", string.Join(",", Options.Scope)));
var request = new HttpRequestMessage(HttpMethod.Post, TokenEndpoint);
request.Headers.Add("User-Agent", Options.UserAgent);
request.Content = new FormUrlEncodedContent(body);
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.SendAsync(request);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string expires = (string) response.expires_in;
string refreshToken = (string) response.refresh_token;
// Get the Reddit user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint);
userRequest.Headers.Add("User-Agent", Options.UserAgent);
userRequest.Headers.Add("Authorization", "bearer " + Uri.EscapeDataString(accessToken) + "");
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new RedditAuthenticatedContext(Context, user, accessToken, expires, refreshToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
if (!string.IsNullOrEmpty(context.Id))
{
context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:reddit:url", context.Link, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:reddit:accesstoken", context.AccessToken, XmlSchemaString, Options.AuthenticationType));
}
context.Identity.AddClaim(new Claim("urn:reddit:overeighteen", context.OverEighteen.ToString()));
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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://ssl.reddit.com/api/v1/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state) +
"&duration=permanent";
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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new RedditReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,252 +0,0 @@
using Microsoft.Owin;
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 Owin.Security.Providers.Slack.Provider;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace Owin.Security.Providers.Slack
{
public class SlackAuthenticationHandler : AuthenticationHandler<SlackAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://slack.com/api/oauth.access";
private const string UserInfoEndpoint = "https://slack.com/api/auth.test";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public SlackAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
// Check for error
if (Request.Query.Get("error") != null)
return new AuthenticationTicket(null, properties);
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
string secret = Options.ClientId + ":" + Options.ClientSecret;
var secretBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(secret));
HttpRequestMessage tokenRequest = new HttpRequestMessage(HttpMethod.Post, TokenEndpoint);
tokenRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", secretBase64);
tokenRequest.Content = new FormUrlEncodedContent(body);
// Request the token
HttpResponseMessage tokenResponse = await httpClient.SendAsync(tokenRequest);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string scope = (string)response.scope;
// Get the Slack user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint + "?token=" + Uri.EscapeDataString(accessToken));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new SlackAuthenticatedContext(Context, user, accessToken, scope);
context.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(context.UserName))
{
context.Identity.AddClaim(new Claim(ClaimsIdentity.DefaultNameClaimType, context.UserName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.TeamId))
{
context.Identity.AddClaim(new Claim("urn:slack:teamid", context.TeamId, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.TeamName))
{
context.Identity.AddClaim(new Claim("urn:slack:teamname", context.TeamName, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.TeamUrl))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Webpage, context.TeamUrl, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://slack.com/oauth/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&state=" + Uri.EscapeDataString(state) +
"&team=" + Uri.EscapeDataString(Options.TeamId);
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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new SlackReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,243 +0,0 @@
using Microsoft.Owin;
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 Owin.Security.Providers.Spotify.Provider;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
namespace Owin.Security.Providers.Spotify
{
public class SpotifyAuthenticationHandler : AuthenticationHandler<SpotifyAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://accounts.spotify.com/api/token";
private const string UserInfoEndpoint = "https://api.spotify.com/v1/me";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public SpotifyAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
// Check for error
if (Request.Query.Get("error") != null)
return new AuthenticationTicket(null, properties);
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
string secret = Options.ClientId + ":" + Options.ClientSecret;
var secretBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(secret));
HttpRequestMessage tokenRequest = new HttpRequestMessage(HttpMethod.Post, TokenEndpoint);
tokenRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic", secretBase64);
tokenRequest.Content = new FormUrlEncodedContent(body);
// Request the token
HttpResponseMessage tokenResponse = await httpClient.SendAsync(tokenRequest);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string refreshToken = (string)response.refresh_token;
string expiresIn = (string)response.expires_in;
// Get the Spotify user
HttpRequestMessage graphRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint);
graphRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage graphResponse = await httpClient.SendAsync(graphRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new SpotifyAuthenticatedContext(Context, user, accessToken, refreshToken, expiresIn);
context.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));
}
if (!string.IsNullOrEmpty(context.ProfilePicture))
{
context.Identity.AddClaim(new Claim("urn:spotify:profilepicture", context.ProfilePicture, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string scope = string.Join(" ", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://accounts.spotify.com/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new SpotifyReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,36 +0,0 @@
using Microsoft.Owin.Logging;
using Newtonsoft.Json;
using Owin.Security.Providers.OpenID;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Text.RegularExpressions;
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 const string UserInfoUri = "http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={0}&steamids={1}";
public SteamAuthenticationHandler(HttpClient httpClient, ILogger logger)
: base(httpClient, logger)
{ }
protected override void SetIdentityInformations(ClaimsIdentity identity, string claimedID, IDictionary<string, string> attributeExchangeProperties)
{
Match accountIDMatch = AccountIDRegex.Match(claimedID);
if (accountIDMatch.Success)
{
string accountID = accountIDMatch.Groups[1].Value;
var getUserInfoTask = _httpClient.GetStringAsync(string.Format(UserInfoUri, Options.ApplicationKey, accountID));
getUserInfoTask.Wait();
string userInfoRaw = getUserInfoTask.Result;
dynamic userInfo = JsonConvert.DeserializeObject<dynamic>(userInfoRaw);
identity.AddClaim(new Claim(ClaimTypes.Name, (string)userInfo.response.players[0].personaname, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationType));
}
}
}
}

View File

@@ -1,241 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Twitch
{
public class TwitchAuthenticationHandler : AuthenticationHandler<TwitchAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public TwitchAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = string.Copy(values.First());
}
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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("code", code));
// Request the token
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Content = new FormUrlEncodedContent(body);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Get the Twitch user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint + "?oauth_token=" + Uri.EscapeDataString(accessToken));
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new TwitchAuthenticatedContext(Context, user, accessToken);
context.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:Twitch:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:Twitch: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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(" ", Options.Scope.Distinct());
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&scope=" + Uri.EscapeDataString(scope) +
"&response_type=" + "code" +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new TwitchReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,26 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Owin.Security.Providers.Untappd
{
internal class ResponseRoot
{
public Meta meta { get; set; }
public Response response { get; set; }
}
public class Meta
{
public int http_code { get; set; }
}
public class Response
{
public string access_token { get; set; }
}
}

View File

@@ -1,241 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.VKontakte.Provider;
namespace Owin.Security.Providers.VKontakte
{
public class VKontakteAuthenticationHandler : AuthenticationHandler<VKontakteAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public VKontakteAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
public override async Task<bool> InvokeAsync()
{
return await InvokeReplyPathAsync();
}
protected override Task ApplyResponseChallengeAsync()
{
if (Response.StatusCode != 401)
{
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri = string.Format("{0}{1}{2}{3}", Request.Scheme, Uri.SchemeDelimiter, Request.Host, Request.PathBase);
string currentUri = string.Format("{0}{1}{2}", baseUri, Request.Path, Request.QueryString);
string redirectUri = string.Format("{0}{1}", baseUri, Options.CallbackPath);
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// comma separated
string scope = string.Join(",", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint = string.Format("{0}?client_id={1}&redirect_uri={2}&scope={3}&state={4}&display={5}",
Options.Endpoints.AuthorizationEndpoint,
Uri.EscapeDataString(Options.ClientId),
Uri.EscapeDataString(redirectUri),
Uri.EscapeDataString(scope),
Uri.EscapeDataString(state),
Uri.EscapeDataString(Options.Display));
Response.Redirect(authorizationEndpoint);
}
return Task.FromResult<object>(null);
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string authorizationCode = GetParameterValueFromRequest("code");
string state = GetParameterValueFromRequest("state");
properties = Options.StateDataFormat.Unprotect(state);
if (properties == null)
{
return null;
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
JObject response = await GetAuthorizationToken(authorizationCode);
string accessToken = (string)response["access_token"];
JObject user = await GetUser(response, accessToken);
VKontakteAuthenticatedContext context = CreateAuthenticatedContext(user, accessToken, 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);
}
private string GetParameterValueFromRequest(string parameterName)
{
string value = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues(parameterName);
if (values != null && values.Count == 1)
{
value = values[0];
}
return value;
}
private VKontakteAuthenticatedContext CreateAuthenticatedContext(JObject user, string accessToken,
AuthenticationProperties properties)
{
var context = new VKontakteAuthenticatedContext(Context, user, accessToken)
{
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));
}
context.Properties = properties;
return context;
}
private async Task<JObject> GetUser(JObject response, string accessToken)
{
int userId = (int)response["user_id"];
// Get the VK user
var userRequestUri = new Uri(string.Format("{0}?access_token={1}&user_id{2}", Options.Endpoints.UserInfoEndpoint, Uri.EscapeDataString(accessToken), userId));
HttpResponseMessage userResponse = await httpClient.GetAsync(userRequestUri, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
var userReposnseAsString = await userResponse.Content.ReadAsStringAsync();
var user = JObject.Parse(userReposnseAsString)["response"];
return (JObject)user[0];
}
private async Task<JObject> GetAuthorizationToken(string authorizationCode)
{
string redirectUri = string.Format("{0}://{1}{2}{3}", Request.Scheme, Request.Host, Request.PathBase, Options.CallbackPath);
// Build up the body for the token request
var body = new Dictionary<string, string>
{
{"code", authorizationCode},
{"redirect_uri", redirectUri},
{"client_id", Options.ClientId},
{"client_secret", Options.ClientSecret}
};
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(Options.Endpoints.TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string tokenResponseAsString = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
JObject response = JObject.Parse(tokenResponseAsString);
return response;
}
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
{
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new VKontakteReturnEndpointContext(Context, ticket)
{
SignInAsAuthenticationType = Options.SignInAsAuthenticationType,
RedirectUri = ticket.Properties.RedirectUri
};
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,220 +0,0 @@
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Owin.Security.Providers.Vimeo
{
public class VimeoAuthenticationHandler : AuthenticationHandler<VimeoAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://api.vimeo.com/oauth/access_token";
private const string AuthorizationEndpoint = "https://api.vimeo.com/oauth/authorize";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public VimeoAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
// Vimeo includes the user information in the response
var context = new VimeoAuthenticatedContext(Context, response.user, accessToken);
context.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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state);
if (!string.IsNullOrWhiteSpace(Options.Scope))
{
authorizationEndpoint += "&scope=" + Uri.EscapeDataString(Options.Scope);
}
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)
{
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new VimeoReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Owin.Security.Providers.VisualStudio {
internal static class Constants {
public const string DefaultAuthenticationType = "Visual Studio Online";
}
}

View File

@@ -1,211 +0,0 @@
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;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.VisualStudio {
public class VisualStudioAuthenticationHandler : AuthenticationHandler<VisualStudioAuthenticationOptions> {
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public VisualStudioAuthenticationHandler(HttpClient httpClient, ILogger logger) {
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync() {
AuthenticationProperties properties = null;
try {
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = "https://" + Request.Host; // Schema must be HTTPS
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"));
body.Add(new KeyValuePair<string, string>("client_assertion", Options.AppSecret));
body.Add(new KeyValuePair<string, string>("grant_type", "urn:ietf:params:oauth:grant-type:jwt-bearer"));
body.Add(new KeyValuePair<string, string>("assertion", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
// 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);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string refreshToken = (string)response.refresh_token;
int expiresIn = (int)response.expires_in;
// Get the Visual Studio Online user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, Options.Endpoints.UserInfoEndpoint);
userRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage userResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
var context = new VisualStudioAuthenticatedContext(Context, user, accessToken, expiresIn, refreshToken);
context.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));
}
if (!string.IsNullOrEmpty(context.Email)) {
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Alias)) {
context.Identity.AddClaim(new Claim("urn:vso:alias", context.Alias, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null) {
string baseUri =
"https" + //Schema must be HTTPS
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri)) {
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
// space separated
string scope = string.Join(" ", Options.Scope);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.AppId) +
"&response_type=Assertion" +
"&state=" + Uri.EscapeDataString(state) +
"&scope=" + Uri.EscapeDataString(scope) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri);
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) {
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null) {
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new VisualStudioReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null) {
ClaimsIdentity 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) {
string 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;
}
return false;
}
}
}

View File

@@ -1,36 +0,0 @@
using Microsoft.Owin.Logging;
using Newtonsoft.Json;
using Owin.Security.Providers.OpenID;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Text.RegularExpressions;
namespace Owin.Security.Providers.Wargaming
{
internal sealed class WargamingAuthenticationHandler : OpenIDAuthenticationHandlerBase<WargamingAuthenticationOptions>
{
private readonly Regex AccountIDRegex = new Regex(@"^https://na.wargaming.net/id/([0-9]{10}).*$", RegexOptions.Compiled);
private const string UserInfoUri = "https://api.worldoftanks.com/wot/account/info/?application_id={0}&account_id={1}&fields=nickname";
public WargamingAuthenticationHandler(HttpClient httpClient, ILogger logger)
: base(httpClient, logger)
{
}
protected override void SetIdentityInformations(ClaimsIdentity identity, string claimedID, IDictionary<string, string> attributeExchangeProperties)
{
Match accountIDMatch = AccountIDRegex.Match(claimedID);
if (accountIDMatch.Success)
{
string accountID = accountIDMatch.Groups[1].Value;
var getUserInfoTask = _httpClient.GetStringAsync(string.Format(UserInfoUri, Options.AppId, accountID));
getUserInfoTask.Wait();
string userInfoRaw = getUserInfoTask.Result;
dynamic userInfo = JsonConvert.DeserializeObject(userInfoRaw);
identity.AddClaim(new Claim(ClaimTypes.Name, (string)userInfo["data"][accountID].nickname, "http://www.w3.org/2001/XMLSchema#string", Options.AuthenticationType));
}
}
}
}

View File

@@ -1,239 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.WordPress
{
public class WordPressAuthenticationHandler : AuthenticationHandler<WordPressAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://public-api.wordpress.com/oauth2/token";
private const string UserInfoEndpoint = "https://public-api.wordpress.com/rest/v1/me";
private const string SiteInfoEndpoint = "https://public-api.wordpress.com/rest/v1/sites/";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public WordPressAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
// Build up the body for the token request
var body = new List<KeyValuePair<string, string>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("code", code));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
// Request the token
HttpResponseMessage tokenResponse =
await httpClient.PostAsync(TokenEndpoint, new FormUrlEncodedContent(body));
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
string blogId = (string)response.blog_id;
string blogUrl = (string)response.blog_url;
// Get the Wordpress user
HttpRequestMessage userRequest = new HttpRequestMessage(HttpMethod.Get, UserInfoEndpoint);
userRequest.Headers.Add("User-Agent", "OWIN OAuth Provider");
userRequest.Headers.Add("Authorization", "BEARER " + accessToken);
HttpResponseMessage graphResponse = await httpClient.SendAsync(userRequest, Request.CallCancelled);
graphResponse.EnsureSuccessStatusCode();
text = await graphResponse.Content.ReadAsStringAsync();
JObject user = JObject.Parse(text);
// Get the site details
HttpRequestMessage siteRequest = new HttpRequestMessage(HttpMethod.Get, SiteInfoEndpoint + blogId);
siteRequest.Headers.Add("User-Agent", "OWIN OAuth Provider");
siteRequest.Headers.Add("Authorization", "BEARER " + accessToken);
HttpResponseMessage siteResponse = await httpClient.SendAsync(siteRequest, Request.CallCancelled);
siteResponse.EnsureSuccessStatusCode();
text = await siteResponse.Content.ReadAsStringAsync();
JObject site = JObject.Parse(text);
var context = new WordPressAuthenticatedContext(Context, user, site, accessToken, blogId, blogUrl);
context.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));
}
if (!string.IsNullOrEmpty(context.Email))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.Email, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
"https://public-api.wordpress.com/oauth2/authorize" +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new WordPressReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
}
}

View File

@@ -1,250 +0,0 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
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 Owin.Security.Providers.Yammer.Provider;
namespace Owin.Security.Providers.Yammer
{
public class YammerAuthenticationHandler : AuthenticationHandler<YammerAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private const string TokenEndpoint = "https://www.yammer.com/oauth2/access_token.json";
private const string UserAuthenticationEndpoint = "https://www.yammer.com/dialog/oauth";
private readonly ILogger logger;
private readonly HttpClient httpClient;
public YammerAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
{
AuthenticationProperties properties = null;
try
{
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> 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;
}
if (code == null)
{
throw new Exception(query["error"] + " - " + query["error_description"]);
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
string endPoint =
TokenEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&client_secret=" + Uri.EscapeDataString(Options.ClientSecret) +
"&code=" + Uri.EscapeDataString(code);
// Request the token
HttpResponseMessage tokenResponse = await httpClient.GetAsync(endPoint);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token.token;
// Get the Yammer user
dynamic user = response.user;
var context = new YammerAuthenticatedContext(Context, user, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
EnsureAcceptedNetwork(Options.AcceptedNetworks, context.Network);
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));
}
if (!string.IsNullOrEmpty(context.PrimaryEmail))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.PrimaryEmail, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Url))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Uri, context.Url, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.AccessToken))
{
context.Identity.AddClaim(new Claim("urn:Yammer:accesstoken", context.AccessToken, 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);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
UserAuthenticationEndpoint +
"?client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new YammerReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
}
return false;
}
private void EnsureAcceptedNetwork(string[] validNetworks, string userNetwork)
{
if (validNetworks != null && validNetworks.Length > 0)
{
bool isValid = false;
foreach (string network in validNetworks)
{
if (userNetwork == network)
{
isValid = true;
break;
}
}
if (!isValid) throw new Exception("User is not in list of accepted networks");
}
}
}
}

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

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

View File

@@ -1,11 +1,96 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
VisualStudioVersion = 12.0.30723.0
# Visual Studio 14
VisualStudioVersion = 14.0.24720.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OwinOAuthProvidersDemo", "OwinOAuthProvidersDemo\OwinOAuthProvidersDemo.csproj", "{5A438007-0C90-4DAC-BAA1-54A32164067F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers", "Owin.Security.Providers\Owin.Security.Providers.csproj", "{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}"
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
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Asana", "src\Owin.Security.Providers.Asana\Owin.Security.Providers.Asana.csproj", "{F3E27220-1D8C-4037-94AA-7B7F4A12F351}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Backlog", "src\Owin.Security.Providers.Backlog\Owin.Security.Providers.Backlog.csproj", "{2DC03778-9EF1-466A-83EC-7D8422DECD23}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.BattleNet", "src\Owin.Security.Providers.BattleNet\Owin.Security.Providers.BattleNet.csproj", "{99A175DA-ADE4-436C-A272-C8AE44B7A086}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Bitbucket", "src\Owin.Security.Providers.Bitbucket\Owin.Security.Providers.Bitbucket.csproj", "{E5212FC7-ABCB-462F-9989-8E022DFFE43C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Buffer", "src\Owin.Security.Providers.Buffer\Owin.Security.Providers.Buffer.csproj", "{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Cosign", "src\Owin.Security.Providers.Cosign\Owin.Security.Providers.Cosign.csproj", "{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.DeviantArt", "src\Owin.Security.Providers.DeviantArt\Owin.Security.Providers.DeviantArt.csproj", "{FABD2E54-976D-41F5-8800-DEE58ACC027C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.DoYouBuzz", "src\Owin.Security.Providers.DoYouBuzz\Owin.Security.Providers.DoYouBuzz.csproj", "{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Dropbox", "src\Owin.Security.Providers.Dropbox\Owin.Security.Providers.Dropbox.csproj", "{CEF697B1-3651-49E5-9060-65F2E26C039C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.EVEOnline", "src\Owin.Security.Providers.EVEOnline\Owin.Security.Providers.EVEOnline.csproj", "{F5DC23F4-5042-4024-9E34-ACA648602BA0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Fitbit", "src\Owin.Security.Providers.Fitbit\Owin.Security.Providers.Fitbit.csproj", "{CA44D014-5A74-4749-A891-1F711FD3A266}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Flickr", "src\Owin.Security.Providers.Flickr\Owin.Security.Providers.Flickr.csproj", "{AF6CBEB8-5638-43D4-839E-C81F305960BE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Foursquare", "src\Owin.Security.Providers.Foursquare\Owin.Security.Providers.Foursquare.csproj", "{8ACD9194-1EFE-4128-AC42-856D856332A4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.GitHub", "src\Owin.Security.Providers.GitHub\Owin.Security.Providers.GitHub.csproj", "{803F9EB7-029C-45AC-AB81-135E60D5BEAE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Gitter", "src\Owin.Security.Providers.Gitter\Owin.Security.Providers.Gitter.csproj", "{42EC50EB-0C51-460C-93A4-1E007BF1F323}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.GooglePlus", "src\Owin.Security.Providers.GooglePlus\Owin.Security.Providers.GooglePlus.csproj", "{D3FEF959-0E0E-4F50-954C-F123A0B629DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.HealthGraph", "src\Owin.Security.Providers.HealthGraph\Owin.Security.Providers.HealthGraph.csproj", "{157BB715-29B2-4202-8A59-CCBACFCBEDD3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Imgur", "src\Owin.Security.Providers.Imgur\Owin.Security.Providers.Imgur.csproj", "{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Instagram", "src\Owin.Security.Providers.Instagram\Owin.Security.Providers.Instagram.csproj", "{041178C4-6131-4D68-9896-CE33124D83A0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.LinkedIn", "src\Owin.Security.Providers.LinkedIn\Owin.Security.Providers.LinkedIn.csproj", "{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Onshape", "src\Owin.Security.Providers.Onshape\Owin.Security.Providers.Onshape.csproj", "{9FEC99F8-6F45-40A2-8200-85381434C79A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.OpenID", "src\Owin.Security.Providers.OpenID\Owin.Security.Providers.OpenID.csproj", "{90C152D7-9C66-4949-9998-C7CE48B593DE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.PayPal", "src\Owin.Security.Providers.PayPal\Owin.Security.Providers.PayPal.csproj", "{F7129064-3DB7-4B79-81D3-80130D664E45}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Reddit", "src\Owin.Security.Providers.Reddit\Owin.Security.Providers.Reddit.csproj", "{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Salesforce", "src\Owin.Security.Providers.Salesforce\Owin.Security.Providers.Salesforce.csproj", "{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Shopify", "src\Owin.Security.Providers.Shopify\Owin.Security.Providers.Shopify.csproj", "{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Slack", "src\Owin.Security.Providers.Slack\Owin.Security.Providers.Slack.csproj", "{3E6F293D-8500-428D-BDC9-27440CC91E16}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.SoundCloud", "src\Owin.Security.Providers.SoundCloud\Owin.Security.Providers.SoundCloud.csproj", "{2C959026-7058-4302-A6C4-DFD10A030585}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Spotify", "src\Owin.Security.Providers.Spotify\Owin.Security.Providers.Spotify.csproj", "{683B4041-A399-40CE-84B8-392F08A6805D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.StackExchange", "src\Owin.Security.Providers.StackExchange\Owin.Security.Providers.StackExchange.csproj", "{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Steam", "src\Owin.Security.Providers.Steam\Owin.Security.Providers.Steam.csproj", "{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.TripIt", "src\Owin.Security.Providers.TripIt\Owin.Security.Providers.TripIt.csproj", "{B35E2616-DC00-48B4-BD58-7E23046257F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Twitch", "src\Owin.Security.Providers.Twitch\Owin.Security.Providers.Twitch.csproj", "{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Untappd", "src\Owin.Security.Providers.Untappd\Owin.Security.Providers.Untappd.csproj", "{3E89ECA3-F4E7-4181-B26B-8250D5151044}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Vimeo", "src\Owin.Security.Providers.Vimeo\Owin.Security.Providers.Vimeo.csproj", "{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.VisualStudio", "src\Owin.Security.Providers.VisualStudio\Owin.Security.Providers.VisualStudio.csproj", "{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.VKontakte", "src\Owin.Security.Providers.VKontakte\Owin.Security.Providers.VKontakte.csproj", "{32D70E31-3799-482A-AC7A-081FF9206FC3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Wargaming", "src\Owin.Security.Providers.Wargaming\Owin.Security.Providers.Wargaming.csproj", "{AA72BFCE-8495-4A4D-988D-F8D490521776}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.WordPress", "src\Owin.Security.Providers.WordPress\Owin.Security.Providers.WordPress.csproj", "{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Xing", "src\Owin.Security.Providers.Xing\Owin.Security.Providers.Xing.csproj", "{D497D8BD-6EF9-4C30-B195-B0DD153418D6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Yahoo", "src\Owin.Security.Providers.Yahoo\Owin.Security.Providers.Yahoo.csproj", "{1765BEDB-9E4B-468C-BAF6-06784CDCED67}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.Yammer", "src\Owin.Security.Providers.Yammer\Owin.Security.Providers.Yammer.csproj", "{8D029A93-E687-4DDF-82B0-700EBBF477F7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Owin.Security.Providers.OpenIDBase", "src\Owin.Security.Providers.OpenIDBase\Owin.Security.Providers.OpenIDBase.csproj", "{4FD7B873-1994-4990-AA40-C37060121494}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -17,10 +102,182 @@ Global
{5A438007-0C90-4DAC-BAA1-54A32164067F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5A438007-0C90-4DAC-BAA1-54A32164067F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5A438007-0C90-4DAC-BAA1-54A32164067F}.Release|Any CPU.Build.0 = Release|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6AD9BA00-1330-426D-8BAE-2D3BC0D976E4}.Release|Any CPU.Build.0 = Release|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A49FAEF-D365-4D25-942C-1CAD03845A5E}.Release|Any CPU.Build.0 = Release|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3E27220-1D8C-4037-94AA-7B7F4A12F351}.Release|Any CPU.Build.0 = Release|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2DC03778-9EF1-466A-83EC-7D8422DECD23}.Release|Any CPU.Build.0 = Release|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Debug|Any CPU.Build.0 = Debug|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Release|Any CPU.ActiveCfg = Release|Any CPU
{99A175DA-ADE4-436C-A272-C8AE44B7A086}.Release|Any CPU.Build.0 = Release|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5212FC7-ABCB-462F-9989-8E022DFFE43C}.Release|Any CPU.Build.0 = Release|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6F75FC1F-D9E9-49B3-A6CE-CFA8FEEA11A5}.Release|Any CPU.Build.0 = Release|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F1F8D6B-7219-46FA-93D3-8D3061A6CBBF}.Release|Any CPU.Build.0 = Release|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FABD2E54-976D-41F5-8800-DEE58ACC027C}.Release|Any CPU.Build.0 = Release|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4550D8BD-05A7-44F8-BBC0-C3D8E7AF2912}.Release|Any CPU.Build.0 = Release|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CEF697B1-3651-49E5-9060-65F2E26C039C}.Release|Any CPU.Build.0 = Release|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5DC23F4-5042-4024-9E34-ACA648602BA0}.Release|Any CPU.Build.0 = Release|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CA44D014-5A74-4749-A891-1F711FD3A266}.Release|Any CPU.Build.0 = Release|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AF6CBEB8-5638-43D4-839E-C81F305960BE}.Release|Any CPU.Build.0 = Release|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8ACD9194-1EFE-4128-AC42-856D856332A4}.Release|Any CPU.Build.0 = Release|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{803F9EB7-029C-45AC-AB81-135E60D5BEAE}.Release|Any CPU.Build.0 = Release|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42EC50EB-0C51-460C-93A4-1E007BF1F323}.Release|Any CPU.Build.0 = Release|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3FEF959-0E0E-4F50-954C-F123A0B629DC}.Release|Any CPU.Build.0 = Release|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{157BB715-29B2-4202-8A59-CCBACFCBEDD3}.Release|Any CPU.Build.0 = Release|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{101841D3-645E-4A44-AF8B-8AAA85CEEA4E}.Release|Any CPU.Build.0 = Release|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{041178C4-6131-4D68-9896-CE33124D83A0}.Release|Any CPU.Build.0 = Release|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FA87825-30E9-48D7-AC4A-39E8F0C2777C}.Release|Any CPU.Build.0 = Release|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9FEC99F8-6F45-40A2-8200-85381434C79A}.Release|Any CPU.Build.0 = Release|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{90C152D7-9C66-4949-9998-C7CE48B593DE}.Release|Any CPU.Build.0 = Release|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7129064-3DB7-4B79-81D3-80130D664E45}.Release|Any CPU.Build.0 = Release|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D0CD86C8-A6F9-4C6C-9BF0-EAA461E7FBAD}.Release|Any CPU.Build.0 = Release|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{827A9D68-0DD4-4C5E-B763-8302FAEEDECC}.Release|Any CPU.Build.0 = Release|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Debug|Any CPU.Build.0 = Debug|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Release|Any CPU.ActiveCfg = Release|Any CPU
{67F12BFB-EB3A-4A86-B5DC-F4C066FDF792}.Release|Any CPU.Build.0 = Release|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E6F293D-8500-428D-BDC9-27440CC91E16}.Release|Any CPU.Build.0 = Release|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C959026-7058-4302-A6C4-DFD10A030585}.Release|Any CPU.Build.0 = Release|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{683B4041-A399-40CE-84B8-392F08A6805D}.Release|Any CPU.Build.0 = Release|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2C0E07ED-F26D-4FF8-8C3D-F760C09A2D5A}.Release|Any CPU.Build.0 = Release|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{312C4ED7-8CA1-4723-9203-ABC694DFDC7C}.Release|Any CPU.Build.0 = Release|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B35E2616-DC00-48B4-BD58-7E23046257F1}.Release|Any CPU.Build.0 = Release|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3CF8734-6AAC-4F59-9A3E-1CBA8582CD48}.Release|Any CPU.Build.0 = Release|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3E89ECA3-F4E7-4181-B26B-8250D5151044}.Release|Any CPU.Build.0 = Release|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{98ECC703-D651-4EAD-A55D-AA3E903AE4D7}.Release|Any CPU.Build.0 = Release|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B19FA31-DDFF-427F-9D73-F860DE74BBC2}.Release|Any CPU.Build.0 = Release|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{32D70E31-3799-482A-AC7A-081FF9206FC3}.Release|Any CPU.Build.0 = Release|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA72BFCE-8495-4A4D-988D-F8D490521776}.Release|Any CPU.Build.0 = Release|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0EDE8223-DD5F-4DB8-A98A-64B1F4591F48}.Release|Any CPU.Build.0 = Release|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D497D8BD-6EF9-4C30-B195-B0DD153418D6}.Release|Any CPU.Build.0 = Release|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1765BEDB-9E4B-468C-BAF6-06784CDCED67}.Release|Any CPU.Build.0 = Release|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D029A93-E687-4DDF-82B0-700EBBF477F7}.Release|Any CPU.Build.0 = Release|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FD7B873-1994-4990-AA40-C37060121494}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@@ -0,0 +1,8 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GIS/@EntryIndexedValue">GIS</s:String>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=Kontakte/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=sreg/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=Untappd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=xing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ReSpeller/UserDictionaries/=en_005Fus/Words/=Xing/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@@ -1,5 +1,4 @@
using System.Web;
using System.Web.Optimization;
using System.Web.Optimization;
namespace OwinOAuthProvidersDemo
{

View File

@@ -1,5 +1,4 @@
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
namespace OwinOAuthProvidersDemo
{

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
using System.Web.Routing;
namespace OwinOAuthProvidersDemo

View File

@@ -1,49 +1,7 @@
using System;
using System.Security.Claims;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Owin;
using Owin.Security.Providers.Asana;
using Owin.Security.Providers.ArcGISOnline;
using Owin.Security.Providers.BattleNet;
using Owin.Security.Providers.Buffer;
using Owin.Security.Providers.DeviantArt;
using Owin.Security.Providers.Dropbox;
using Owin.Security.Providers.EveOnline;
using Owin.Security.Providers.Flickr;
using Owin.Security.Providers.Foursquare;
using Owin.Security.Providers.GitHub;
using Owin.Security.Providers.Gitter;
using Owin.Security.Providers.GooglePlus;
using Owin.Security.Providers.GooglePlus.Provider;
using Owin.Security.Providers.HealthGraph;
using Owin.Security.Providers.Imgur;
using Owin.Security.Providers.Instagram;
using Owin.Security.Providers.LinkedIn;
using Owin.Security.Providers.OpenID;
using Owin.Security.Providers.PayPal;
using Owin.Security.Providers.Reddit;
using Owin.Security.Providers.Salesforce;
using Owin.Security.Providers.Slack;
using Owin.Security.Providers.SoundCloud;
using Owin.Security.Providers.Spotify;
using Owin.Security.Providers.StackExchange;
using Owin.Security.Providers.Steam;
using Owin.Security.Providers.Shopify;
using Owin.Security.Providers.TripIt;
using Owin.Security.Providers.Twitch;
using Owin.Security.Providers.Untappd;
using Owin.Security.Providers.Wargaming;
using Owin.Security.Providers.WordPress;
using Owin.Security.Providers.Yahoo;
using Owin.Security.Providers.Backlog;
using Owin.Security.Providers.DoYouBuzz;
using Owin.Security.Providers.Vimeo;
using Owin.Security.Providers.Fitbit;
using Owin.Security.Providers.Onshape;
using Owin.Security.Providers.VKontakte;
using Owin.Security.Providers.Xing;
namespace OwinOAuthProvidersDemo
{

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
@@ -137,7 +133,7 @@ namespace OwinOAuthProvidersDemo.Controllers
[ValidateAntiForgeryToken]
public async Task<ActionResult> Manage(ManageUserViewModel model)
{
bool hasPassword = HasPassword();
var hasPassword = HasPassword();
ViewBag.HasLocalPassword = hasPassword;
ViewBag.ReturnUrl = Url.Action("Manage");
if (hasPassword)
@@ -415,12 +411,12 @@ namespace OwinOAuthProvidersDemo.Controllers
var properties = new AuthenticationProperties() { RedirectUri = RedirectUri };
if (UserId != null)
{
properties.Dictionary[XsrfKey] = this.UserId;
properties.Dictionary[XsrfKey] = UserId;
}
if (!string.IsNullOrWhiteSpace(this.ShopName))
if (!string.IsNullOrWhiteSpace(ShopName))
{
properties.Dictionary[ShopNameKey] = this.ShopName;
properties.Dictionary[ShopNameKey] = ShopName;
}
context.HttpContext.GetOwinContext().Authentication.Challenge(properties, LoginProvider);

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
namespace OwinOAuthProvidersDemo.Controllers
{

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

View File

@@ -20,6 +20,7 @@
<IISExpressAnonymousAuthentication>enabled</IISExpressAnonymousAuthentication>
<IISExpressWindowsAuthentication>disabled</IISExpressWindowsAuthentication>
<IISExpressUseClassicPipelineMode>false</IISExpressUseClassicPipelineMode>
<UseGlobalApplicationHostFile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -40,69 +41,77 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Antlr3.Runtime, Version=3.5.0.2, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Antlr.3.5.0.2\lib\Antlr3.Runtime.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\EntityFramework.6.1.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Identity.Core.2.1.0\lib\net45\Microsoft.AspNet.Identity.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.EntityFramework, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Identity.EntityFramework.2.1.0\lib\net45\Microsoft.AspNet.Identity.EntityFramework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.AspNet.Identity.Owin, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Identity.Owin.2.1.0\lib\net45\Microsoft.AspNet.Identity.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.2.1.0\lib\net45\Microsoft.Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Host.SystemWeb.2.1.0\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.2.1.0\lib\net45\Microsoft.Owin.Security.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Cookies, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Cookies.2.1.0\lib\net45\Microsoft.Owin.Security.Cookies.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Facebook, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Facebook.2.1.0\lib\net45\Microsoft.Owin.Security.Facebook.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Google, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Google.2.1.0\lib\net45\Microsoft.Owin.Security.Google.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.MicrosoftAccount, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.MicrosoftAccount.2.1.0\lib\net45\Microsoft.Owin.Security.MicrosoftAccount.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.OAuth, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.OAuth.2.1.0\lib\net45\Microsoft.Owin.Security.OAuth.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Owin.Security.Twitter, Version=2.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Owin.Security.Twitter.2.1.0\lib\net45\Microsoft.Owin.Security.Twitter.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.4\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.Data" />
@@ -114,32 +123,32 @@
<Reference Include="System.Core" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Web.Helpers, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.Helpers.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Mvc, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Mvc.5.2.0\lib\net45\System.Web.Mvc.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Optimization, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Web.Optimization.1.1.3\lib\net40\System.Web.Optimization.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.Razor.3.2.0\lib\net45\System.Web.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Deployment, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Deployment.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.AspNet.WebPages.3.2.0\lib\net45\System.Web.WebPages.Razor.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Web" />
@@ -150,22 +159,13 @@
<Reference Include="System.Configuration" />
<Reference Include="System.Web.Services" />
<Reference Include="System.EnterpriseServices" />
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Private>True</Private>
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http">
</Reference>
<Reference Include="System.Net.Http.WebRequest">
</Reference>
<Reference Include="WebGrease, Version=1.6.5135.21930, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WebGrease.1.6.0\lib\WebGrease.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Reference Include="Owin">
<HintPath>..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
@@ -195,14 +195,13 @@
<Content Include="fonts\glyphicons-halflings-regular.woff" />
<Content Include="fonts\glyphicons-halflings-regular.ttf" />
<Content Include="fonts\glyphicons-halflings-regular.eot" />
<Content Include="Content\bootstrap-theme.css.map" />
<Content Include="Content\bootstrap.css.map" />
<Content Include="Content\bootstrap-theme.css.map" />
<None Include="Scripts\jquery-2.1.1.intellisense.js" />
<Content Include="Scripts\bootstrap.js" />
<Content Include="Scripts\bootstrap.min.js" />
<Content Include="Scripts\jquery-2.1.1.js" />
<Content Include="Scripts\jquery-2.1.1.min.js" />
<Content Include="Scripts\jquery-2.1.1.min.map" />
<None Include="Scripts\jquery.validate-vsdoc.js" />
<Content Include="Scripts\jquery.validate.js" />
<Content Include="Scripts\jquery.validate.min.js" />
@@ -245,13 +244,9 @@
</ItemGroup>
<ItemGroup>
<Content Include="packages.config" />
<None Include="Project_Readme.html" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Owin.Security.Providers\Owin.Security.Providers.csproj">
<Project>{6ad9ba00-1330-426d-8bae-2d3bc0d976e4}</Project>
<Name>Owin.Security.Providers</Name>
</ProjectReference>
<Content Include="Scripts\jquery-2.1.1.min.map" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>

View File

@@ -1,151 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Your ASP.NET application</title>
<style>
body {
background: #fff;
color: #505050;
font: 14px 'Segoe UI', tahoma, arial, helvetica, sans-serif;
margin: 20px;
padding: 0;
}
#header {
background: #efefef;
padding: 0;
}
h1 {
font-size: 48px;
font-weight: normal;
margin: 0;
padding: 0 30px;
line-height: 150px;
}
p {
font-size: 20px;
color: #fff;
background: #969696;
padding: 0 30px;
line-height: 50px;
}
#main {
padding: 5px 30px;
}
.section {
width: 21.7%;
float: left;
margin: 0 0 0 4%;
}
.section h2 {
font-size: 13px;
text-transform: uppercase;
margin: 0;
border-bottom: 1px solid silver;
padding-bottom: 12px;
margin-bottom: 8px;
}
.section.first {
margin-left: 0;
}
.section.first h2 {
font-size: 24px;
text-transform: none;
margin-bottom: 25px;
border: none;
}
.section.first li {
border-top: 1px solid silver;
padding: 8px 0;
}
.section.last {
margin-right: 0;
}
ul {
list-style: none;
padding: 0;
margin: 0;
line-height: 20px;
}
li {
padding: 4px 0;
}
a {
color: #267cb2;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div id="header">
<h1>Your ASP.NET application</h1>
<p>Congratulations! You've created a project</p>
</div>
<div id="main">
<div class="section first">
<h2>This application consists of:</h2>
<ul>
<li>Sample pages showing basic nav between Home, About, and Contact</li>
<li>Theming using <a href="http://go.microsoft.com/fwlink/?LinkID=320754">Bootstrap</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320755">Authentication</a>, if selected, shows how to register and sign in</li>
<li>ASP.NET features managed using <a href="http://go.microsoft.com/fwlink/?LinkID=320756">NuGet</a></li>
</ul>
</div>
<div class="section">
<h2>Customize app</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320757">Get started with ASP.NET MVC</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320758">Change the site's theme</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320759">Add more libraries using NuGet</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320760">Configure authentication</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320761">Customize information about the website users</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320762">Get information from social providers</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320763">Add HTTP services using ASP.NET Web API</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320764">Secure your web API</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320765">Add real-time web with ASP.NET SignalR</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320766">Add components using Scaffolding</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320767">Test your app with Browser Link</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320768">Share your project</a></li>
</ul>
</div>
<div class="section">
<h2>Deploy</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320769">Ensure your app is ready for production</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320770">Windows Azure</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320771">Hosting providers</a></li>
</ul>
</div>
<div class="section last">
<h2>Get help</h2>
<ul>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320772">Get help</a></li>
<li><a href="http://go.microsoft.com/fwlink/?LinkID=320773">Get more templates</a></li>
</ul>
</div>
</div>
</body>
</html>

View File

@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following

View File

@@ -1,9 +1,10 @@
/// <autosync enabled="true" />
/// <reference path="bootstrap.js" />
/// <reference path="bootstrap.min.js" />
/// <reference path="jquery.validate.min.js" />
/// <reference path="jquery.validate.unobtrusive.min.js" />
/// <reference path="jquery-2.1.1.js" />
/// <reference path="jquery.validate.js" />
/// <reference path="jquery.validate.unobtrusive.js" />
/// <reference path="jquery-2.1.1.min.js" />
/// <reference path="modernizr-2.6.2.js" />
/// <reference path="modernizr-2.7.2.js" />
/// <reference path="respond.js" />
/// <reference path="respond.matchmedia.addlistener.js" />
/// <reference path="respond.matchmedia.addlistener.min.js" />
/// <reference path="respond.min.js" />

View File

@@ -49,7 +49,7 @@ window.Modernizr = (function( window, document, undefined ) {
var version = '2.6.2',
Modernizr = {},
modernizr = {},
/*>>cssclasses*/
// option for enabling the HTML classes to be added
@@ -207,7 +207,7 @@ window.Modernizr = (function( window, document, undefined ) {
// ...
isEventSupported = (function() {
var TAGNAMES = {
var tagnames = {
'select': 'input', 'change': 'input',
'submit': 'form', 'reset': 'form',
'error': 'img', 'load': 'img', 'abort': 'img'
@@ -215,7 +215,7 @@ window.Modernizr = (function( window, document, undefined ) {
function isEventSupported( eventName, element ) {
element = element || document.createElement(TAGNAMES[eventName] || 'div');
element = element || document.createElement(tagnames[eventName] || 'div');
eventName = 'on' + eventName;
// When using `setAttribute`, IE skips "unload", WebKit skips "unload" and "resize", whereas `in` "catches" those
@@ -248,11 +248,11 @@ window.Modernizr = (function( window, document, undefined ) {
// TODO :: Add flag for hasownprop ? didn't last time
// hasOwnProperty shim by kangax needed for Safari 2.0 support
_hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
if ( !is(hasOwnProperty, 'undefined') && !is(hasOwnProperty.call, 'undefined') ) {
hasOwnProp = function (object, property) {
return _hasOwnProperty.call(object, property);
return hasOwnProperty.call(object, property);
};
}
else {
@@ -278,9 +278,9 @@ window.Modernizr = (function( window, document, undefined ) {
if (this instanceof bound) {
var F = function(){};
F.prototype = target.prototype;
var self = new F();
var f = function(){};
f.prototype = target.prototype;
var self = new f();
var result = target.apply(
self,
@@ -370,7 +370,7 @@ window.Modernizr = (function( window, document, undefined ) {
* testDOMProps is a generic DOM property test; if a browser supports
* a certain property, it won't return undefined for it.
*/
function testDOMProps( props, obj, elem ) {
function testDomProps( props, obj, elem ) {
for ( var i in props ) {
var item = obj[props[i]];
if ( item !== undefined) {
@@ -410,7 +410,7 @@ window.Modernizr = (function( window, document, undefined ) {
// otherwise, they called .prefixed('requestAnimationFrame', window[, elem])
} else {
props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
return testDOMProps(props, prefixed, elem);
return testDomProps(props, prefixed, elem);
}
}
/*>>testallprops*/
@@ -445,7 +445,7 @@ window.Modernizr = (function( window, document, undefined ) {
};
tests['canvastext'] = function() {
return !!(Modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
return !!(modernizr['canvas'] && is(document.createElement('canvas').getContext('2d').fillText, 'function'));
};
// webk.it/70117 is tracking a legit WebGL feature detect proposal
@@ -881,7 +881,7 @@ window.Modernizr = (function( window, document, undefined ) {
// Only input placeholder is tested while textarea's placeholder is not.
// Currently Safari 4 and Opera 11 have support only for the input placeholder
// Both tests are available in feature-detects/forms-placeholder.js
Modernizr['input'] = (function( props ) {
modernizr['input'] = (function( props ) {
for ( var i = 0, len = props.length; i < len; i++ ) {
attrs[ props[i] ] = !!(props[i] in inputElem);
}
@@ -901,7 +901,7 @@ window.Modernizr = (function( window, document, undefined ) {
// containing each input type with its corresponding true/false value
// Big thanks to @miketaylr for the html5 forms expertise. miketaylr.com/
Modernizr['inputtypes'] = (function(props) {
modernizr['inputtypes'] = (function(props) {
for ( var i = 0, bool, inputElemType, defaultView, len = props.length; i < len; i++ ) {
@@ -969,15 +969,15 @@ window.Modernizr = (function( window, document, undefined ) {
// then based on that boolean, define an appropriate className
// and push it into an array of classes we'll join later.
featureName = feature.toLowerCase();
Modernizr[featureName] = tests[feature]();
modernizr[featureName] = tests[feature]();
classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
classes.push((modernizr[featureName] ? '' : 'no-') + featureName);
}
}
/*>>webforms*/
// input tests need to run.
Modernizr.input || webforms();
modernizr.input || webforms();
/*>>webforms*/
@@ -989,24 +989,24 @@ window.Modernizr = (function( window, document, undefined ) {
* @param feature - String naming the feature
* @param test - Function returning true if feature is supported, false if not
*/
Modernizr.addTest = function ( feature, test ) {
modernizr.addTest = function ( feature, test ) {
if ( typeof feature == 'object' ) {
for ( var key in feature ) {
if ( hasOwnProp( feature, key ) ) {
Modernizr.addTest( key, feature[ key ] );
modernizr.addTest( key, feature[ key ] );
}
}
} else {
feature = feature.toLowerCase();
if ( Modernizr[feature] !== undefined ) {
if ( modernizr[feature] !== undefined ) {
// we're going to quit if you're trying to overwrite an existing test
// if we were to allow it, we'd do this:
// var re = new RegExp("\\b(no-)?" + feature + "\\b");
// docElement.className = docElement.className.replace( re, '' );
// but, no rly, stuff 'em.
return Modernizr;
return modernizr;
}
test = typeof test == 'function' ? test() : test;
@@ -1014,11 +1014,11 @@ window.Modernizr = (function( window, document, undefined ) {
if (typeof enableClasses !== "undefined" && enableClasses) {
docElement.className += ' ' + (test ? '' : 'no-') + feature;
}
Modernizr[feature] = test;
modernizr[feature] = test;
}
return Modernizr; // allow chaining.
return modernizr; // allow chaining.
};
@@ -1046,7 +1046,7 @@ window.Modernizr = (function( window, document, undefined ) {
var expando = '_html5shiv';
/** The id for the the documents expando */
var expanID = 0;
var expanId = 0;
/** Cached data for each document */
var expandoData = {};
@@ -1115,9 +1115,9 @@ window.Modernizr = (function( window, document, undefined ) {
var data = expandoData[ownerDocument[expando]];
if (!data) {
data = {};
expanID++;
ownerDocument[expando] = expanID;
expandoData[expanID] = data;
expanId++;
ownerDocument[expando] = expanId;
expandoData[expanId] = data;
}
return data;
}
@@ -1318,15 +1318,15 @@ window.Modernizr = (function( window, document, undefined ) {
/*>>shiv*/
// Assign private properties to the return object with prefix
Modernizr._version = version;
modernizr._version = version;
// expose these for the plugin API. Look in the source for how to join() them against your input
/*>>prefixes*/
Modernizr._prefixes = prefixes;
modernizr._prefixes = prefixes;
/*>>prefixes*/
/*>>domprefixes*/
Modernizr._domPrefixes = domPrefixes;
Modernizr._cssomPrefixes = cssomPrefixes;
modernizr._domPrefixes = domPrefixes;
modernizr._cssomPrefixes = cssomPrefixes;
/*>>domprefixes*/
/*>>mq*/
@@ -1338,20 +1338,20 @@ window.Modernizr = (function( window, document, undefined ) {
// Modernizr.mq('(min-width:0)')
// usage:
// Modernizr.mq('only screen and (max-width:768)')
Modernizr.mq = testMediaQuery;
modernizr.mq = testMediaQuery;
/*>>mq*/
/*>>hasevent*/
// Modernizr.hasEvent() detects support for a given event, with an optional element to test on
// Modernizr.hasEvent('gesturestart', elem)
Modernizr.hasEvent = isEventSupported;
modernizr.hasEvent = isEventSupported;
/*>>hasevent*/
/*>>testprop*/
// Modernizr.testProp() investigates whether a given style property is recognized
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testProp('pointerEvents')
Modernizr.testProp = function(prop){
modernizr.testProp = function(prop){
return testProps([prop]);
};
/*>>testprop*/
@@ -1361,14 +1361,14 @@ window.Modernizr = (function( window, document, undefined ) {
// or any of its vendor-prefixed variants, is recognized
// Note that the property names must be provided in the camelCase variant.
// Modernizr.testAllProps('boxSizing')
Modernizr.testAllProps = testPropsAll;
modernizr.testAllProps = testPropsAll;
/*>>testallprops*/
/*>>teststyles*/
// Modernizr.testStyles() allows you to add custom styles to the document and test an element afterwards
// Modernizr.testStyles('#modernizr { position:absolute }', function(elem, rule){ ... })
Modernizr.testStyles = injectElementWithStyles;
modernizr.testStyles = injectElementWithStyles;
/*>>teststyles*/
@@ -1392,7 +1392,7 @@ window.Modernizr = (function( window, document, undefined ) {
// },
// transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
Modernizr.prefixed = function(prop, obj, elem){
modernizr.prefixed = function(prop, obj, elem){
if(!obj) {
return testPropsAll(prop, 'pfx');
} else {
@@ -1411,6 +1411,6 @@ window.Modernizr = (function( window, document, undefined ) {
(enableClasses ? ' js ' + classes.join(' ') : '');
/*>>cssclasses*/
return Modernizr;
return modernizr;
})(this, this.document);

View File

@@ -1,6 +1,4 @@
@using OwinOAuthProvidersDemo.Models;
@using Microsoft.AspNet.Identity;
@{
@{
ViewBag.Title = "Manage Account";
}

View File

@@ -55,8 +55,14 @@ For above listed provider implementation guide, visit Jerrie Pelser's blog - [Be
To use these providers you will need to install the ```Owin.Security.Providers``` NuGet package.
```
PM> Install-Package Owin.Security.Providers
PM> Install-Package Owin.Security.Providers.*
```
Where * is the name of the provider you need e.g.:
```
PM> Install-Package Owin.Security.Providers.GitHub
```
I haven't published all of the providers yet as of 4/12/2016.
## Contributions
@@ -82,6 +88,7 @@ A big thanks goes out to all these contributors without whom this would not have
* Jaspalsinh Chauhan (https://github.com/jsinh)
* Jason Loeffler (https://github.com/jmloeffler)
* Ben Foster (https://github.com/benfoster)
* Jonathan Peterson (https://github.com/eonasdan)
For most accurate and up to date list of contributors please see https://github.com/RockstarLabs/OwinOAuthProviders/graphs/contributors

BIN
nuget/NuGet.exe Normal file

Binary file not shown.

View File

@@ -8,9 +8,9 @@ namespace Owin.Security.Providers.ArcGISOnline
ArcGISOnlineAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException("app");
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException("options");
throw new ArgumentNullException(nameof(options));
app.Use(typeof(ArcGISOnlineAuthenticationMiddleware), app, options);

View File

@@ -0,0 +1,231 @@
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.ArcGISOnline
{
public class ArcGISOnlineAuthenticationHandler : AuthenticationHandler<ArcGISOnlineAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public ArcGISOnlineAuthenticationHandler(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 = 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;
// Get the ArcGISOnline 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.ArcGISOnlineUser>(text);
var context = new ArcGISOnlineAuthenticatedContext(Context, user, accessToken)
{
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:ArcGISOnline:name", context.Name, XmlSchemaString, Options.AuthenticationType));
}
if (!string.IsNullOrEmpty(context.Link))
{
context.Identity.AddClaim(new Claim("urn:ArcGISOnline: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 ArcGISOnlineReturnEndpointContext(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

@@ -7,49 +7,48 @@ using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Properties;
namespace Owin.Security.Providers.ArcGISOnline
{
public class ArcGISOnlineAuthenticationMiddleware : AuthenticationMiddleware<ArcGISOnlineAuthenticationOptions>
{
private readonly HttpClient httpClient;
private readonly ILogger logger;
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public ArcGISOnlineAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
ArcGISOnlineAuthenticationOptions options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
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,
if (string.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientSecret"));
logger = app.CreateLogger<ArcGISOnlineAuthenticationMiddleware>();
_logger = app.CreateLogger<ArcGISOnlineAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new ArcGISOnlineAuthenticationProvider();
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = app.CreateDataProtector(
var dataProtector = app.CreateDataProtector(
typeof (ArcGISOnlineAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v2");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024*1024*10,
};
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin ArcGISOnline middleware");
httpClient.DefaultRequestHeaders.ExpectContinue = false;
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin ArcGISOnline middleware");
_httpClient.DefaultRequestHeaders.ExpectContinue = false;
}
/// <summary>
@@ -62,24 +61,22 @@ namespace Owin.Security.Providers.ArcGISOnline
/// </returns>
protected override AuthenticationHandler<ArcGISOnlineAuthenticationOptions> CreateHandler()
{
return new ArcGISOnlineAuthenticationHandler(httpClient, logger);
return new ArcGISOnlineAuthenticationHandler(_httpClient, _logger);
}
private HttpMessageHandler ResolveHttpMessageHandler(ArcGISOnlineAuthenticationOptions options)
private static HttpMessageHandler ResolveHttpMessageHandler(ArcGISOnlineAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}

View File

@@ -123,8 +123,7 @@ namespace Owin.Security.Providers.ArcGISOnline
/// <summary>
/// Initializes a new <see cref="ArcGISOnlineAuthenticationOptions" />
/// </summary>
public ArcGISOnlineAuthenticationOptions()
: base("ArcGIS Online")
public ArcGISOnlineAuthenticationOptions() : base("ArcGIS Online")
{
Caption = Constants.DefaultAuthenticationType;
CallbackPath = new PathString("/signin-arcgis-online");

View File

@@ -2,6 +2,6 @@
{
internal static class Constants
{
public const string DefaultAuthenticationType = "ArcGIS Online";
internal const string DefaultAuthenticationType = "ArcGIS Online";
}
}

View File

@@ -0,0 +1,105 @@
<?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>{8A49FAEF-D365-4D25-942C-1CAD03845A5E}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.ArcGISOnline</RootNamespace>
<AssemblyName>Owin.Security.Providers.ArcGISOnline</AssemblyName>
<TargetFrameworkVersion>v4.5.2</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>
<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.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="ArcGISOnlineAuthenticationExtensions.cs" />
<Compile Include="ArcGISOnlineAuthenticationHandler.cs" />
<Compile Include="ArcGISOnlineAuthenticationMiddleware.cs" />
<Compile Include="ArcGISOnlineAuthenticationOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Provider\ArcGISOnlineAuthenticatedContext.cs" />
<Compile Include="Provider\ArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="Provider\ArcGISOnlineReturnEndpointContext.cs" />
<Compile Include="Provider\ArcGISOnlineUser.cs" />
<Compile Include="Provider\IArcGISOnlineAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="C:\projects\GitHub\OwinOAuthProviders\Owin.Security.Providers.ArcGISOnline\Owin.Security.Providers.ArcGISOnline.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</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>
<PostBuildEvent>if $(ConfigurationName) == Release $(SolutionDir)\nuget\NuGet pack "$(ProjectDir)Owin.Security.Providers.ArcGISOnline.nuspec" -o "$(SolutionDir)Output" -version @(VersionNumber)</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers.ArcGISOnline</id>
<version>2.0.0</version>
<authors>Jerrie Pelser, Eonasdan and contributors</authors>
<owners>Eonasdan</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/Eonasdan/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds a ArcGISOnline OAuth provider for OWIN to use with ASP.NET
</description>
<summary>
Providers have now been split into their own packages from Owin.Security.Providers
</summary>
<releaseNotes>
</releaseNotes>
<copyright>Copyright 2016</copyright>
<tags>owin katana oauth ArcGISOnline</tags>
<dependencies>
<dependency id="Microsoft.Owin.Security" version="2.1.0" />
<dependency id="Newtonsoft.Json" version="6.0.1" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\Owin.Security.Providers.ArcGISOnline.dll" target="lib\net45" />
</files>
</package>

View File

@@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.ArcGISOnline")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.ArcGISOnline")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("edf75484-ed98-4f6c-bd71-f4d8fa3fc019")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -1,13 +1,9 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Security.Claims;
using System.Linq;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Provider;
using Newtonsoft.Json.Linq;
using Owin.Security.Providers.ArcGISOnline.Provider;
namespace Owin.Security.Providers.ArcGISOnline
@@ -28,11 +24,11 @@ namespace Owin.Security.Providers.ArcGISOnline
{
AccessToken = accessToken;
Id = user.user.username;
Name = user.user.fullName;
Id = user.User.Username;
Name = user.User.FullName;
Link = "https://www.arcgis.com/sharing/rest/community/users/" + Id;
UserName = Id;
Email = user.user.email;
Email = user.User.Email;
}
/// <summary>
@@ -43,7 +39,7 @@ namespace Owin.Security.Providers.ArcGISOnline
/// <summary>
/// Gets the ArcGISOnline user ID
/// </summary>
public string Id { get; private set; }
public string Id { get; }
/// <summary>
/// Gets the user's name

View File

@@ -28,7 +28,7 @@ namespace Owin.Security.Providers.ArcGISOnline
public Func<ArcGISOnlineReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever ArcGISOnline succesfully authenticates a user
/// Invoked whenever ArcGISOnline 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>

View File

@@ -0,0 +1,14 @@
namespace Owin.Security.Providers.ArcGISOnline.Provider
{
public class ArcGISOnlineUser
{
public User User { get; set; }
}
public class User
{
public string Username { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
}
}

View File

@@ -8,7 +8,7 @@ namespace Owin.Security.Providers.ArcGISOnline
public interface IArcGISOnlineAuthenticationProvider
{
/// <summary>
/// Invoked whenever ArcGISOnline succesfully authenticates a user
/// Invoked whenever ArcGISOnline 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>

View File

@@ -1,14 +1,14 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.34003
// 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.Properties {
namespace Owin.Security.Providers.ArcGISOnline {
using System;
@@ -39,7 +39,7 @@ namespace Owin.Security.Providers.Properties {
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.Properties.Resources", typeof(Resources).Assembly);
var temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.ArcGISOnline.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<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="8.0.3" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
</packages>

View File

@@ -8,9 +8,9 @@ namespace Owin.Security.Providers.Asana
AsanaAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException("app");
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException("options");
throw new ArgumentNullException(nameof(options));
app.Use(typeof(AsanaAuthenticationMiddleware), app, options);

View File

@@ -4,13 +4,11 @@ using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.Owin;
using Microsoft.Owin.Infrastructure;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace Owin.Security.Providers.Asana
{
@@ -18,13 +16,13 @@ namespace Owin.Security.Providers.Asana
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger logger;
private readonly HttpClient httpClient;
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public AsanaAuthenticationHandler(HttpClient httpClient, ILogger logger)
{
this.httpClient = httpClient;
this.logger = logger;
_httpClient = httpClient;
_logger = logger;
}
protected override async Task<AuthenticationTicket> AuthenticateCoreAsync()
@@ -36,8 +34,8 @@ namespace Owin.Security.Providers.Asana
string code = null;
string state = null;
IReadableStringCollection query = Request.Query;
IList<string> values = query.GetValues("code");
var query = Request.Query;
var values = query.GetValues("code");
if (values != null && values.Count == 1)
{
code = values[0];
@@ -55,21 +53,23 @@ namespace Owin.Security.Providers.Asana
}
// OAuth2 10.12 CSRF
if (!ValidateCorrelationId(properties, logger))
if (!ValidateCorrelationId(properties, _logger))
{
return new AuthenticationTicket(null, properties);
}
string requestPrefix = Request.Scheme + "://" + Request.Host;
string redirectUri = requestPrefix + Request.PathBase + Options.CallbackPath;
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>>();
body.Add(new KeyValuePair<string, string>("grant_type", "authorization_code"));
body.Add(new KeyValuePair<string, string>("client_id", Options.ClientId));
body.Add(new KeyValuePair<string, string>("client_secret", Options.ClientSecret));
body.Add(new KeyValuePair<string, string>("redirect_uri", redirectUri));
body.Add(new KeyValuePair<string, string>("code", code));
var body = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("grant_type", "authorization_code"),
new KeyValuePair<string, string>("client_id", Options.ClientId),
new KeyValuePair<string, string>("client_secret", Options.ClientSecret),
new KeyValuePair<string, string>("redirect_uri", redirectUri),
new KeyValuePair<string, string>("code", code)
};
/*Your app makes a POST request to https://app.asana.com/-/oauth_token, passing the parameters as part of a standard form-encoded post body.
grant_type - required Must be authorization_code
@@ -83,13 +83,13 @@ namespace Owin.Security.Providers.Asana
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.Endpoints.TokenEndpoint);
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
requestMessage.Content = new FormUrlEncodedContent(body);
HttpResponseMessage tokenResponse = await httpClient.SendAsync(requestMessage);
var tokenResponse = await _httpClient.SendAsync(requestMessage);
tokenResponse.EnsureSuccessStatusCode();
string text = await tokenResponse.Content.ReadAsStringAsync();
var text = await tokenResponse.Content.ReadAsStringAsync();
// Deserializes the token response
dynamic response = JsonConvert.DeserializeObject<dynamic>(text);
string accessToken = (string)response.access_token;
var accessToken = (string)response.access_token;
/*
* In the response, you will receive a JSON payload with the following parameters:
@@ -102,11 +102,13 @@ namespace Owin.Security.Providers.Asana
// Get the Asana user
var context = new AsanaAuthenticatedContext(Context, response.data, accessToken);
context.Identity = new ClaimsIdentity(
Options.AuthenticationType,
ClaimsIdentity.DefaultNameClaimType,
ClaimsIdentity.DefaultRoleClaimType);
var context = new AsanaAuthenticatedContext(Context, response.data, accessToken)
{
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));
@@ -127,7 +129,7 @@ namespace Owin.Security.Providers.Asana
}
catch (Exception ex)
{
logger.WriteError(ex.Message);
_logger.WriteError(ex.Message);
}
return new AuthenticationTicket(null, properties);
}
@@ -139,45 +141,44 @@ namespace Owin.Security.Providers.Asana
return Task.FromResult<object>(null);
}
AuthenticationResponseChallenge challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
var challenge = Helper.LookupChallenge(Options.AuthenticationType, Options.AuthenticationMode);
if (challenge != null)
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))
{
string baseUri =
Request.Scheme +
Uri.SchemeDelimiter +
Request.Host +
Request.PathBase;
properties.RedirectUri = currentUri;
}
string currentUri =
baseUri +
Request.Path +
Request.QueryString;
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string redirectUri =
baseUri +
Options.CallbackPath;
AuthenticationProperties properties = challenge.Properties;
if (string.IsNullOrEmpty(properties.RedirectUri))
{
properties.RedirectUri = currentUri;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
string state = Options.StateDataFormat.Protect(properties);
string authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state)
;
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
Options.Endpoints.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&redirect_uri=" + Uri.EscapeDataString(redirectUri) +
"&state=" + Uri.EscapeDataString(state)
;
/*Your app redirects the user to https://app.asana.com/-/oauth_authorize, passing parameters along as a standard query string:
/*Your app redirects the user to https://app.asana.com/-/oauth_authorize, passing parameters along as a standard query string:
client_id - required The Client ID uniquely identifies the application making the request.
redirect_uri - required The URI to redirect to on success or error. This must match the Redirect URL specified in the application settings.
@@ -185,8 +186,7 @@ namespace Owin.Security.Providers.Asana
state - optional Encodes state of the app, which will be returned verbatim in the response and can be used to match the response up to a given request.
*/
Response.Redirect(authorizationEndpoint);
}
Response.Redirect(authorizationEndpoint);
return Task.FromResult<object>(null);
}
@@ -198,50 +198,47 @@ namespace Owin.Security.Providers.Asana
private async Task<bool> InvokeReplyPathAsync()
{
if (Options.CallbackPath.HasValue && Options.CallbackPath == Request.Path)
if (!Options.CallbackPath.HasValue || Options.CallbackPath != Request.Path) return false;
// TODO: error responses
var ticket = await AuthenticateAsync();
if (ticket == null)
{
// TODO: error responses
AuthenticationTicket ticket = await AuthenticateAsync();
if (ticket == null)
{
logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
var context = new AsanaReturnEndpointContext(Context, ticket);
context.SignInAsAuthenticationType = Options.SignInAsAuthenticationType;
context.RedirectUri = ticket.Properties.RedirectUri;
await Options.Provider.ReturnEndpoint(context);
if (context.SignInAsAuthenticationType != null &&
context.Identity != null)
{
ClaimsIdentity 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)
{
string 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;
_logger.WriteWarning("Invalid return state, unable to redirect.");
Response.StatusCode = 500;
return true;
}
return false;
var context = new AsanaReturnEndpointContext(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

@@ -7,49 +7,48 @@ using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Properties;
namespace Owin.Security.Providers.Asana
{
public class AsanaAuthenticationMiddleware : AuthenticationMiddleware<AsanaAuthenticationOptions>
{
private readonly HttpClient httpClient;
private readonly ILogger logger;
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public AsanaAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
AsanaAuthenticationOptions options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
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,
if (string.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientSecret"));
logger = app.CreateLogger<AsanaAuthenticationMiddleware>();
_logger = app.CreateLogger<AsanaAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new AsanaAuthenticationProvider();
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = app.CreateDataProtector(
var dataProtector = app.CreateDataProtector(
typeof (AsanaAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024*1024*10,
};
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin Asana middleware");
httpClient.DefaultRequestHeaders.ExpectContinue = false;
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft Owin Asana middleware");
_httpClient.DefaultRequestHeaders.ExpectContinue = false;
}
/// <summary>
@@ -62,24 +61,22 @@ namespace Owin.Security.Providers.Asana
/// </returns>
protected override AuthenticationHandler<AsanaAuthenticationOptions> CreateHandler()
{
return new AsanaAuthenticationHandler(httpClient, logger);
return new AsanaAuthenticationHandler(_httpClient, _logger);
}
private HttpMessageHandler ResolveHttpMessageHandler(AsanaAuthenticationOptions options)
private static HttpMessageHandler ResolveHttpMessageHandler(AsanaAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security;

View File

@@ -0,0 +1,104 @@
<?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>{F3E27220-1D8C-4037-94AA-7B7F4A12F351}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.Asana</RootNamespace>
<AssemblyName>Owin.Security.Providers.Asana</AssemblyName>
<TargetFrameworkVersion>v4.5.2</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>
<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.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="AsanaAuthenticationExtensions.cs" />
<Compile Include="AsanaAuthenticationHandler.cs" />
<Compile Include="AsanaAuthenticationMiddleware.cs" />
<Compile Include="AsanaAuthenticationOptions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Provider\AsanaAuthenticatedContext.cs" />
<Compile Include="Provider\AsanaAuthenticationProvider.cs" />
<Compile Include="Provider\AsanaReturnEndpointContext.cs" />
<Compile Include="Provider\IAsanaAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="C:\projects\GitHub\OwinOAuthProviders\Owin.Security.Providers.Asana\Owin.Security.Providers.Asana.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</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>
<PostBuildEvent>if $(ConfigurationName) == Release $(SolutionDir)\nuget\NuGet pack "$(ProjectDir)Owin.Security.Providers.Asana.nuspec" -o "$(SolutionDir)Output" -version @(VersionNumber)</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers.Asana</id>
<version>2.0.0</version>
<authors>Jerrie Pelser, Eonasdan and contributors</authors>
<owners>Eonasdan</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/Eonasdan/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds a Asana OAuth provider for OWIN to use with ASP.NET
</description>
<summary>
Providers have now been split into their own packages from Owin.Security.Providers
</summary>
<releaseNotes>
</releaseNotes>
<copyright>Copyright 2016</copyright>
<tags>owin katana oauth Asana</tags>
<dependencies>
<dependency id="Microsoft.Owin.Security" version="2.1.0" />
<dependency id="Newtonsoft.Json" version="6.0.1" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\Owin.Security.Providers.Asana.dll" target="lib\net45" />
</files>
</package>

View File

@@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.Asana")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.Asana")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("2dd55191-411e-4f28-8051-0f60eb996a53")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -1,7 +1,5 @@
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
using System;
using System.Globalization;
using System.Security.Claims;
using Microsoft.Owin;
using Microsoft.Owin.Security;

View File

@@ -28,7 +28,7 @@ namespace Owin.Security.Providers.Asana
public Func<AsanaReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever Asana succesfully authenticates a user
/// Invoked whenever Asana 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>

View File

@@ -16,10 +16,7 @@ namespace Owin.Security.Providers.Asana
/// </summary>
/// <param name="context">OWIN environment</param>
/// <param name="ticket">The authentication ticket</param>
public AsanaReturnEndpointContext(
IOwinContext context,
AuthenticationTicket ticket)
: base(context, ticket)
public AsanaReturnEndpointContext(IOwinContext context,AuthenticationTicket ticket) : base(context, ticket)
{
}
}

View File

@@ -8,7 +8,7 @@ namespace Owin.Security.Providers.Asana
public interface IAsanaAuthenticationProvider
{
/// <summary>
/// Invoked whenever Asana succesfully authenticates a user
/// Invoked whenever Asana 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>

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.Asana {
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)) {
var temp = new global::System.Resources.ResourceManager("Owin.Security.Providers.Asana.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="net452" />
<package id="Microsoft.Owin.Security" version="3.0.1" targetFramework="net452" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net452" />
<package id="Owin" version="1.0" targetFramework="net452" />
</packages>

View File

@@ -8,9 +8,9 @@ namespace Owin.Security.Providers.Backlog
BacklogAuthenticationOptions options)
{
if (app == null)
throw new ArgumentNullException("app");
throw new ArgumentNullException(nameof(app));
if (options == null)
throw new ArgumentNullException("options");
throw new ArgumentNullException(nameof(options));
app.Use(typeof(BacklogAuthenticationMiddleware), app, options);

View File

@@ -0,0 +1,237 @@
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 System.Net.Http.Headers;
namespace Owin.Security.Providers.Backlog
{
public class BacklogAuthenticationHandler : AuthenticationHandler<BacklogAuthenticationOptions>
{
private const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
private readonly ILogger _logger;
private readonly HttpClient _httpClient;
public BacklogAuthenticationHandler(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 = 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)
};
// Get token
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint);
tokenRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
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 response = JsonConvert.DeserializeObject<dynamic>(text);
var accessToken = (string)response.access_token;
var expires = (string) response.expires_in;
string refreshToken = null;
if (response.refresh_token != null)
refreshToken = (string) response.refresh_token;
var tokenType = (string)response.token_type;
// Get the Backlog user
var userRequest = new HttpRequestMessage(HttpMethod.Get, Options.UserInfoEndpoint);
userRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
userRequest.Headers.Authorization = new AuthenticationHeaderValue(tokenType, Uri.EscapeDataString(accessToken));
var userResponse = await _httpClient.SendAsync(userRequest, Request.CallCancelled);
userResponse.EnsureSuccessStatusCode();
text = await userResponse.Content.ReadAsStringAsync();
var user = JObject.Parse(text);
var context = new BacklogAuthenticatedContext(Context, user, accessToken, expires, refreshToken)
{
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));
}
if (!string.IsNullOrEmpty(context.MailAddress))
{
context.Identity.AddClaim(new Claim(ClaimTypes.Email, context.MailAddress, 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;
}
// OAuth2 10.12 CSRF
GenerateCorrelationId(properties);
var state = Options.StateDataFormat.Protect(properties);
var authorizationEndpoint =
Options.AuthorizationEndpoint +
"?response_type=code" +
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
"&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 BacklogReturnEndpointContext(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

@@ -7,46 +7,45 @@ using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler;
using Microsoft.Owin.Security.DataProtection;
using Microsoft.Owin.Security.Infrastructure;
using Owin.Security.Providers.Properties;
namespace Owin.Security.Providers.Backlog
{
public class BacklogAuthenticationMiddleware : AuthenticationMiddleware<BacklogAuthenticationOptions>
{
private readonly HttpClient httpClient;
private readonly ILogger logger;
private readonly HttpClient _httpClient;
private readonly ILogger _logger;
public BacklogAuthenticationMiddleware(OwinMiddleware next, IAppBuilder app,
BacklogAuthenticationOptions options)
: base(next, options)
{
if (String.IsNullOrWhiteSpace(Options.ClientId))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
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,
if (string.IsNullOrWhiteSpace(Options.ClientSecret))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ClientSecret"));
if (String.IsNullOrWhiteSpace(Options.ContractName))
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
if (string.IsNullOrWhiteSpace(Options.ContractName))
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
Resources.Exception_OptionMustBeProvided, "ContractName"));
logger = app.CreateLogger<BacklogAuthenticationMiddleware>();
_logger = app.CreateLogger<BacklogAuthenticationMiddleware>();
if (Options.Provider == null)
Options.Provider = new BacklogAuthenticationProvider();
if (Options.StateDataFormat == null)
{
IDataProtector dataProtector = app.CreateDataProtector(
var dataProtector = app.CreateDataProtector(
typeof (BacklogAuthenticationMiddleware).FullName,
Options.AuthenticationType, "v1");
Options.StateDataFormat = new PropertiesDataFormat(dataProtector);
}
if (String.IsNullOrEmpty(Options.SignInAsAuthenticationType))
if (string.IsNullOrEmpty(Options.SignInAsAuthenticationType))
Options.SignInAsAuthenticationType = app.GetDefaultSignInAsAuthenticationType();
httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
_httpClient = new HttpClient(ResolveHttpMessageHandler(Options))
{
Timeout = Options.BackchannelTimeout,
MaxResponseContentBufferSize = 1024*1024*10
@@ -63,24 +62,22 @@ namespace Owin.Security.Providers.Backlog
/// </returns>
protected override AuthenticationHandler<BacklogAuthenticationOptions> CreateHandler()
{
return new BacklogAuthenticationHandler(httpClient, logger);
return new BacklogAuthenticationHandler(_httpClient, _logger);
}
private HttpMessageHandler ResolveHttpMessageHandler(BacklogAuthenticationOptions options)
private static HttpMessageHandler ResolveHttpMessageHandler(BacklogAuthenticationOptions options)
{
HttpMessageHandler handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
var handler = options.BackchannelHttpHandler ?? new WebRequestHandler();
// If they provided a validator, apply it or fail.
if (options.BackchannelCertificateValidator != null)
if (options.BackchannelCertificateValidator == null) return handler;
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
// Set the cert validate callback
var webRequestHandler = handler as WebRequestHandler;
if (webRequestHandler == null)
{
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
}
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
return handler;
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security;
@@ -77,7 +76,7 @@ namespace Owin.Security.Providers.Backlog
get
{
var ub = new UriBuilder(TempTokenEndpoint);
ub.Host = ub.Host.Replace("contractname", this.ContractName);
ub.Host = ub.Host.Replace("contractname", ContractName);
return ub.Uri.ToString();
}
@@ -88,7 +87,7 @@ namespace Owin.Security.Providers.Backlog
get
{
var ub = new UriBuilder(TempUserInfoEndpoint);
ub.Host = ub.Host.Replace("contractname", this.ContractName);
ub.Host = ub.Host.Replace("contractname", ContractName);
return ub.Uri.ToString();
}
@@ -99,7 +98,7 @@ namespace Owin.Security.Providers.Backlog
get
{
var ub = new UriBuilder(TempAuthorizationEndpoint);
ub.Host = ub.Host.Replace("contractname", this.ContractName);
ub.Host = ub.Host.Replace("contractname", ContractName);
return ub.Uri.ToString();
}

View File

@@ -0,0 +1,104 @@
<?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>{2DC03778-9EF1-466A-83EC-7D8422DECD23}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Owin.Security.Providers.Backlog</RootNamespace>
<AssemblyName>Owin.Security.Providers.Backlog</AssemblyName>
<TargetFrameworkVersion>v4.5.2</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>
<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.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="BacklogAuthenticationExtensions.cs" />
<Compile Include="BacklogAuthenticationHandler.cs" />
<Compile Include="BacklogAuthenticationMiddleware.cs" />
<Compile Include="BacklogAuthenticationOptions.cs" />
<Compile Include="Constants.cs" />
<Compile Include="Provider\BacklogAuthenticatedContext.cs" />
<Compile Include="Provider\BacklogAuthenticationProvider.cs" />
<Compile Include="Provider\BacklogReturnEndpointContext.cs" />
<Compile Include="Provider\IGBacklogAuthenticationProvider.cs" />
<Compile Include="Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="C:\projects\GitHub\OwinOAuthProviders\Owin.Security.Providers.Backlog\Owin.Security.Providers.Backlog.nuspec" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</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>
<PostBuildEvent>if $(ConfigurationName) == Release $(SolutionDir)\nuget\NuGet pack "$(ProjectDir)Owin.Security.Providers.Backlog.nuspec" -o "$(SolutionDir)Output" -version @(VersionNumber)</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>Owin.Security.Providers.Backlog</id>
<version>2.0.0</version>
<authors>Jerrie Pelser, Eonasdan and contributors</authors>
<owners>Eonasdan</owners>
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
<projectUrl>https://github.com/Eonasdan/OwinOAuthProviders</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>
Adds a Backlog OAuth provider for OWIN to use with ASP.NET
</description>
<summary>
Providers have now been split into their own packages from Owin.Security.Providers
</summary>
<releaseNotes>
</releaseNotes>
<copyright>Copyright 2016</copyright>
<tags>owin katana oauth Backlog</tags>
<dependencies>
<dependency id="Microsoft.Owin.Security" version="2.1.0" />
<dependency id="Newtonsoft.Json" version="6.0.1" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\Owin.Security.Providers.Backlog.dll" target="lib\net45" />
</files>
</package>

View File

@@ -0,0 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("Owin.Security.Providers.Backlog")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Owin.Security.Providers.Backlog")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("59898d6e-035f-44ce-b4da-c79ffefdf6b3")]
[assembly: AssemblyVersion("2.0.0.0")]
[assembly: AssemblyFileVersion("2.0.0.0")]

View File

@@ -2,7 +2,6 @@
using System;
using System.Globalization;
using System.Linq;
using System.Security.Claims;
using Microsoft.Owin;
using Microsoft.Owin.Security;
@@ -21,9 +20,9 @@ namespace Owin.Security.Providers.Backlog
/// </summary>
/// <param name="context">The OWIN environment</param>
/// <param name="user">The JSON-serialized user</param>
/// <param name="person"></param>
/// <param name="accessToken">Google+ Access token</param>
/// <param name="expires">Seconds until expiration</param>
/// <param name="refreshToken"></param>
public BacklogAuthenticatedContext(IOwinContext context, JObject user, string accessToken, string expires, string refreshToken)
: base(context)
{
@@ -32,7 +31,7 @@ namespace Owin.Security.Providers.Backlog
RefreshToken = refreshToken;
int expiresValue;
if (Int32.TryParse(expires, NumberStyles.Integer, CultureInfo.InvariantCulture, out expiresValue))
if (int.TryParse(expires, NumberStyles.Integer, CultureInfo.InvariantCulture, out expiresValue))
{
ExpiresIn = TimeSpan.FromSeconds(expiresValue);
}

View File

@@ -28,7 +28,7 @@ namespace Owin.Security.Providers.Backlog
public Func<BacklogReturnEndpointContext, Task> OnReturnEndpoint { get; set; }
/// <summary>
/// Invoked whenever Google+ succesfully authenticates a user
/// Invoked whenever Google+ 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>

View File

@@ -8,7 +8,7 @@ namespace Owin.Security.Providers.Backlog
public interface IBacklogAuthenticationProvider
{
/// <summary>
/// Invoked whenever Google+ succesfully authenticates a user
/// Invoked whenever Google+ 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>

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