You can customize the GoogleOAuth2AuthenticationOptions in your MVC5 Startup.Auth.cs file to request the offline Access Code and Refresh tokens for use against Google's OAuth2 api's.
in this example I am collecting the values passed from google to the OWIN OAuth2 middleware and adding them to claims accessible in your Callback method.
var googleCreds = new GoogleOAuth2AuthenticationOptions
{
ClientId = "[replace with your google console issued client id]",
ClientSecret = "[replace with your google console issued client secret]",
Provider = new Microsoft.Owin.Security.Google.GoogleOAuth2AuthenticationProvider
{
OnApplyRedirect = context =>
{
string redirect = context.RedirectUri;
redirect += "&access_type=offline";
redirect += "&approval_prompt=force";
redirect += "&include_granted_scopes=true";
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));
if (context.User.GetValue("hd") != null)
{
context.Identity.AddClaim(new Claim("urn:tokens:google:hd", context.User.GetValue("hd").ToString()));
}
context.Identity.AddClaim(new Claim("urn:tokens:google:accesstokenexpiry", DateTime.UtcNow.Add(expiryDuration).ToString()));
return System.Threading.Tasks.Task.FromResult<object>(null);
}
}
};
googleCreds.Scope.Add("openid");
googleCreds.Scope.Add("email");
app.UseGoogleAuthentication(googleCreds);
Now you can access these claim values from your callback method. For example:
var loginInfo = AuthenticationManager.GetExternalLoginInfo();
string GoogleAccessCode = String.Empty;
if (loginInfo.ExternalIdentity.Claims.FirstOrDefault(c => c.Type.Equals("urn:tokens:google:accesstoken")) != null)
{
GoogleAccessCode = loginInfo.ExternalIdentity.Claims.FirstOrDefault(c => c.Type.Equals("urn:tokens:google:accesstoken")).toString();
}
At beginning of the authentication sequence, or after you've finished with AuthenticationManager.GetExternalLoginInfo(), you can clear the external authentication cookie that's floating around to prevent any problematic duplicate cookies building up:
if (Request.Cookies[".AspNet.ExternalCookie"] != null)
{
var c = new System.Web.HttpCookie(".AspNet.ExternalCookie");
c.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(c);
}