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:
63
.gitignore
vendored
63
.gitignore
vendored
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
namespace Owin.Security.Providers.OpenID
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
internal const string DefaultAuthenticationType = "OpenID";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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")]
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
8
OwinOAuthProviders.sln.DotSettings
Normal file
8
OwinOAuthProviders.sln.DotSettings
Normal 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>
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,4 @@
|
||||
using System.Web;
|
||||
using System.Web.Optimization;
|
||||
using System.Web.Optimization;
|
||||
|
||||
namespace OwinOAuthProvidersDemo
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Mvc;
|
||||
|
||||
namespace OwinOAuthProvidersDemo
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
@using OwinOAuthProvidersDemo.Models;
|
||||
@using Microsoft.AspNet.Identity;
|
||||
@{
|
||||
@{
|
||||
ViewBag.Title = "Manage Account";
|
||||
}
|
||||
|
||||
|
||||
@@ -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
BIN
nuget/NuGet.exe
Normal file
Binary file not shown.
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,16 +61,15 @@ 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)
|
||||
@@ -79,7 +77,6 @@ namespace Owin.Security.Providers.ArcGISOnline
|
||||
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
|
||||
}
|
||||
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
@@ -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");
|
||||
@@ -2,6 +2,6 @@
|
||||
{
|
||||
internal static class Constants
|
||||
{
|
||||
public const string DefaultAuthenticationType = "ArcGIS Online";
|
||||
internal const string DefaultAuthenticationType = "ArcGIS Online";
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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")]
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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;
|
||||
7
src/Owin.Security.Providers.ArcGISOnline/packages.config
Normal file
7
src/Owin.Security.Providers.ArcGISOnline/packages.config
Normal 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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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(
|
||||
var context = new AsanaAuthenticatedContext(Context, response.data, accessToken)
|
||||
{
|
||||
Identity = new ClaimsIdentity(
|
||||
Options.AuthenticationType,
|
||||
ClaimsIdentity.DefaultNameClaimType,
|
||||
ClaimsIdentity.DefaultRoleClaimType);
|
||||
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,26 +141,25 @@ 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)
|
||||
{
|
||||
string baseUri =
|
||||
if (challenge == null) return Task.FromResult<object>(null);
|
||||
var baseUri =
|
||||
Request.Scheme +
|
||||
Uri.SchemeDelimiter +
|
||||
Request.Host +
|
||||
Request.PathBase;
|
||||
|
||||
string currentUri =
|
||||
var currentUri =
|
||||
baseUri +
|
||||
Request.Path +
|
||||
Request.QueryString;
|
||||
|
||||
string redirectUri =
|
||||
var redirectUri =
|
||||
baseUri +
|
||||
Options.CallbackPath;
|
||||
|
||||
AuthenticationProperties properties = challenge.Properties;
|
||||
var properties = challenge.Properties;
|
||||
if (string.IsNullOrEmpty(properties.RedirectUri))
|
||||
{
|
||||
properties.RedirectUri = currentUri;
|
||||
@@ -167,8 +168,8 @@ namespace Owin.Security.Providers.Asana
|
||||
// OAuth2 10.12 CSRF
|
||||
GenerateCorrelationId(properties);
|
||||
|
||||
string state = Options.StateDataFormat.Protect(properties);
|
||||
string authorizationEndpoint =
|
||||
var state = Options.StateDataFormat.Protect(properties);
|
||||
var authorizationEndpoint =
|
||||
Options.Endpoints.AuthorizationEndpoint +
|
||||
"?response_type=code" +
|
||||
"&client_id=" + Uri.EscapeDataString(Options.ClientId) +
|
||||
@@ -186,7 +187,6 @@ namespace Owin.Security.Providers.Asana
|
||||
*/
|
||||
|
||||
Response.Redirect(authorizationEndpoint);
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
@@ -198,28 +198,29 @@ 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
|
||||
|
||||
AuthenticationTicket ticket = await AuthenticateAsync();
|
||||
var ticket = await AuthenticateAsync();
|
||||
if (ticket == null)
|
||||
{
|
||||
logger.WriteWarning("Invalid return state, unable to redirect.");
|
||||
_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;
|
||||
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)
|
||||
{
|
||||
ClaimsIdentity grantIdentity = context.Identity;
|
||||
var grantIdentity = context.Identity;
|
||||
if (!string.Equals(grantIdentity.AuthenticationType, context.SignInAsAuthenticationType, StringComparison.Ordinal))
|
||||
{
|
||||
grantIdentity = new ClaimsIdentity(grantIdentity.Claims, context.SignInAsAuthenticationType, grantIdentity.NameClaimType, grantIdentity.RoleClaimType);
|
||||
@@ -227,9 +228,8 @@ namespace Owin.Security.Providers.Asana
|
||||
Context.Authentication.SignIn(context.Properties, grantIdentity);
|
||||
}
|
||||
|
||||
if (!context.IsRequestCompleted && context.RedirectUri != null)
|
||||
{
|
||||
string redirectUri = context.RedirectUri;
|
||||
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
|
||||
@@ -237,11 +237,8 @@ namespace Owin.Security.Providers.Asana
|
||||
}
|
||||
Response.Redirect(redirectUri);
|
||||
context.RequestCompleted();
|
||||
}
|
||||
|
||||
return context.IsRequestCompleted;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,16 +61,15 @@ 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)
|
||||
@@ -79,7 +77,6 @@ namespace Owin.Security.Providers.Asana
|
||||
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
|
||||
}
|
||||
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using Microsoft.Owin;
|
||||
using Microsoft.Owin.Security;
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
15
src/Owin.Security.Providers.Asana/Properties/AssemblyInfo.cs
Normal file
15
src/Owin.Security.Providers.Asana/Properties/AssemblyInfo.cs
Normal 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")]
|
||||
@@ -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;
|
||||
@@ -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>
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
81
src/Owin.Security.Providers.Asana/Resources.Designer.cs
generated
Normal file
81
src/Owin.Security.Providers.Asana/Resources.Designer.cs
generated
Normal 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 '{0}' 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
src/Owin.Security.Providers.Asana/Resources.resx
Normal file
126
src/Owin.Security.Providers.Asana/Resources.resx
Normal 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>
|
||||
7
src/Owin.Security.Providers.Asana/packages.config
Normal file
7
src/Owin.Security.Providers.Asana/packages.config
Normal 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>
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,16 +62,15 @@ 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)
|
||||
@@ -80,7 +78,6 @@ namespace Owin.Security.Providers.Backlog
|
||||
throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch);
|
||||
}
|
||||
webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate;
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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")]
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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>
|
||||
@@ -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
Reference in New Issue
Block a user