OWIN Authorization Server and External Login with Google / Facebook
I had a question for a long time.
So, I read this article and downloaded the sample code. Very good examples of using OWIN to create a Google Signed Authorization Server. It also includes 4 clients for a grant for an authorization code, a grant for a client mandate, an implicit grant, and a mandate for a resource owner password.
For the sake of brevity, I'm only going to put the startup config file here, then my problem and questions. Also, I found my problem using Implicit Grant client. Here we go...
Startup.cs
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
// Enable Application Sign In Cookie
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Application",
AuthenticationMode = AuthenticationMode.Passive,
LoginPath = new PathString(Paths.LoginPath),
LogoutPath = new PathString(Paths.LogoutPath),
});
// Enable External Sign In Cookie
app.SetDefaultSignInAsAuthenticationType("External");
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "External",
AuthenticationMode = AuthenticationMode.Passive,
CookieName = CookieAuthenticationDefaults.CookiePrefix + "External",
ExpireTimeSpan = TimeSpan.FromMinutes(2),
});
// Enable google authentication
//var googleOptions = new GoogleOAuth2AuthenticationOptions
//{
// Caption = "Google+",
// ClientId = "blablabla.apps.googleusercontent.com",
// ClientSecret = "Q1zNmqf-U3ZffeZgcTPh760j",
// CallbackPath = new PathString("/OAuth/Authorize"),
// Provider = new GoogleOAuth2AuthenticationProvider
// {
// OnAuthenticated = async context =>
// {
// context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirst(ClaimTypes.Name).Value));
// context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.Identity.FindFirst(ClaimTypes.Email).Value));
// context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.User.GetValue("picture").ToString()));
// context.Identity.AddClaim(new Claim(ClaimTypes.Name, context.User.GetValue("profile").ToString()));
// context.Identity.AddClaim(new Claim("Token", context.AccessToken));
// }
// }
//};
//googleOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
//googleOptions.Scope.Add("https://www.googleapis.com/auth/plus.login");
//app.UseGoogleAuthentication(googleOptions);
app.UseGoogleAuthentication();
// Setup Authorization Server
app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
AuthorizeEndpointPath = new PathString(Paths.AuthorizePath),
TokenEndpointPath = new PathString(Paths.TokenPath),
ApplicationCanDisplayErrors = true,
AllowInsecureHttp = true,
// Authorization server provider which controls the lifecycle of Authorization Server
Provider = new OAuthAuthorizationServerProvider
{
OnValidateClientRedirectUri = ValidateClientRedirectUri,
OnValidateClientAuthentication = ValidateClientAuthentication,
OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
OnGrantClientCredentials = GrantClientCredetails
},
// Authorization code provider which creates and receives authorization code
AuthorizationCodeProvider = new AuthenticationTokenProvider
{
OnCreate = CreateAuthenticationCode,
OnReceive = ReceiveAuthenticationCode,
},
// Refresh token provider which creates and receives referesh token
RefreshTokenProvider = new AuthenticationTokenProvider
{
OnCreate = CreateRefreshToken,
OnReceive = ReceiveRefreshToken,
}
});
}
private Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
{
if (context.ClientId == Clients.Client1.Id)
{
context.Validated(Clients.Client1.RedirectUrl);
}
else if (context.ClientId == Clients.Client2.Id)
{
context.Validated(Clients.Client2.RedirectUrl);
}
return Task.FromResult(0);
}
private Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId;
string clientSecret;
if (context.TryGetBasicCredentials(out clientId, out clientSecret) ||
context.TryGetFormCredentials(out clientId, out clientSecret))
{
if (clientId == Clients.Client1.Id && clientSecret == Clients.Client1.Secret)
{
context.Validated();
}
else if (clientId == Clients.Client2.Id && clientSecret == Clients.Client2.Secret)
{
context.Validated();
}
}
return Task.FromResult(0);
}
private Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(context.UserName, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(identity);
return Task.FromResult(0);
}
private Task GrantClientCredetails(OAuthGrantClientCredentialsContext context)
{
var identity = new ClaimsIdentity(new GenericIdentity(context.ClientId, OAuthDefaults.AuthenticationType), context.Scope.Select(x => new Claim("urn:oauth:scope", x)));
context.Validated(identity);
return Task.FromResult(0);
}
private readonly ConcurrentDictionary<string, string> _authenticationCodes =
new ConcurrentDictionary<string, string>(StringComparer.Ordinal);
private void CreateAuthenticationCode(AuthenticationTokenCreateContext context)
{
context.SetToken(Guid.NewGuid().ToString("n") + Guid.NewGuid().ToString("n"));
_authenticationCodes[context.Token] = context.SerializeTicket();
}
private void ReceiveAuthenticationCode(AuthenticationTokenReceiveContext context)
{
string value;
if (_authenticationCodes.TryRemove(context.Token, out value))
{
context.DeserializeTicket(value);
}
}
private void CreateRefreshToken(AuthenticationTokenCreateContext context)
{
context.SetToken(context.SerializeTicket());
}
private void ReceiveRefreshToken(AuthenticationTokenReceiveContext context)
{
context.DeserializeTicket(context.Token);
}
}
Now, notice that there is a piece of code that has been commented out. Here is the key and the confusion.
The source code looks like this: app.UseGoogleAuthentication (); ... So this code works great with get go (and for those looking to download and test this code, it's ready to go, just press F5).
Now I understand that this code still allows someone to "authenticate" with Google just to get a "verified user" response and then create their own validator / token (LOCAL AUTHORITY).
The problem comes when I want to extend a little more than google authentication. I want to actually collect more data from google (besides valid / invalid google user). As soon as I uncomment these lines, the authorization part of the authorization server will stop. I don't get an exception or whatever, it just keeps spinning.
Does anyone have any experience with this specific issue?
Thank!
source to share
No one has answered this question yet
Check out similar questions: