I am building a MVC 5 web application that uses cookie authentication as primary authentication method.
Our application flow goes like this:
- First time user signs up with username/password to create an IdentityUser.
- User signs in with his username/password
- User associates one or more Google and/or Microsoft accounts with his "local" account.
- OWIN Google and Microsoft providers handle external authentication.
- We use simple delegate method to read returned access_token and refresh_token and store it as identity claims.
- We use access token to make API calls server side.
- We use refresh token to get new access token when one is expired.
The question is, what is the best place to implemnt access token validation, expiration and renewal. I would really appreciate if somebody could lead me to a right direction.
var googleCreds = new GoogleOAuth2AuthenticationOptions
{
ClientId = "833250754551-qg564a5g29f0l37q0egqimcoklpjf6dj.apps.googleusercontent.com",
ClientSecret = "YpY_u07KQU4kjhPWH5vuiMzz"
Provider = new Microsoft.Owin.Security.Google.GoogleOAuth2AuthenticationProvider
{
OnApplyRedirect = context =>
{
var queryString = HttpContext.Current.Request.QueryString.ToString();
var queryParms = HttpUtility.ParseQueryString(queryString);
string redirect = context.RedirectUri;
redirect += "&access_type=offline";
redirect += "&approval_prompt=force";
redirect += "&include_granted_scopes=true";
var uri = new Uri(redirect);
if ((!string.IsNullOrEmpty(queryParms.Get("scope"))))
{
var scope = queryParms.Get("scope");
var redirectQueryString = HttpUtility.ParseQueryString(uri.Query);
switch (scope)
{
case "GooglePlus":
redirectQueryString.Set("scope", "https://www.googleapis.com/auth/plus.login");
break;
case "YoutTube":
redirectQueryString.Set("scope", "https://gdata.youtube.com");
break;
default:
throw new Exception("Invalid scope passed in: scope: " + scope);
}
redirect = uri.GetLeftPart(UriPartial.Path) + "?" + redirectQueryString.ToString();
}
context.Response.Redirect(redirect);
},
OnAuthenticated = context =>
{
TimeSpan expiryDuration = context.ExpiresIn ?? new TimeSpan();
context.Identity.AddClaim(new Claim("urn:tokens:google:email", context.Email));
context.Identity.AddClaim(new Claim("urn:tokens:google:url", context.GivenName));
if (!String.IsNullOrEmpty(context.RefreshToken))
{
context.Identity.AddClaim(new Claim("urn:tokens:google:refreshtoken", context.RefreshToken));
}
context.Identity.AddClaim(new Claim("urn:tokens:google:accesstoken", context.AccessToken));
context.Identity.AddClaim(new Claim("urn:tokens:google:accesstokenexpiry", DateTime.Now.Add(expiryDuration).ToString()));
return Task.FromResult<object>(null);
}
}
};
app.UseGoogleAuthentication(googleCreds);