We want to make an STS that outsources the authentication to google.
Following the steps stated in https://developers.google.com/accounts/docs/OAuth2Login?hl=es-ES we have the following code in the Login.aspx generated by the sts web site template in vs2010:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["code"] != null)
{
//I'm coming from google, already authenticated
FormsAuthentication.SetAuthCookie(GetUserName(Request.QueryString["code"]), false);
Response.Redirect("default.aspx");
}
else
{
//I want to authenticate
Response.Redirect(
"https://accounts.google.com/o/oauth2/auth?" +
"response_type=code&" +
"client_id=988046895016.apps.googleusercontent.com&" +
"redirect_uri=" + HttpUtility.UrlEncode("https://localhost/GmailSTS/login.aspx") + "&" +
"scope=" + HttpUtility.UrlEncode("https://www.googleapis.com/auth/userinfo.email")
);
}
}
But I get an error beacuse wa is not specified in the QueryString, debugging the samples and the generated template I saw that wa,wtrealm,wctx and wct are the parameters needed so I used the state parameter so they roundtrip and get them back:
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["code"] != null)
{
//I'm coming from google, already authenticated
FormsAuthentication.SetAuthCookie("johannsw", false);
String lQueryStrings = HttpUtility.UrlDecode(Request.QueryString["state"]);
lQueryStrings.Replace('?', '&');
Response.Redirect("default.aspx" + "?" + lQueryStrings);
}
else
{
//I want to authenticate
String lState = String.Empty;
foreach (var key in Request.QueryString.AllKeys)
{
if (String.Equals("wa", key) ||
String.Equals("wtrealm", key) ||
String.Equals("wctx", key) ||
String.Equals("wct", key))
lState += key + "=" + Request.QueryString[key] + "&";
}
lState = lState.Remove(lState.Length - 1);
Response.Redirect(
"https://accounts.google.com/o/oauth2/auth?" +
"response_type=code&" +
"client_id=988046895016.apps.googleusercontent.com&" +
"redirect_uri=" + HttpUtility.UrlEncode("https://localhost/GmailSTS/login.aspx") + "&" +
"scope=" + HttpUtility.UrlEncode("https://www.googleapis.com/auth/userinfo.email") + "&" +
"state=" + HttpUtility.UrlEncode(lState)
);
}
}
but now I get an error saying "The HTTP verb POST used to access path '/WebSite1/' is not allowed."
Any hints? Thanks!
Well finally I made it. Here is how I solved it just in case it helps someone else:
Login.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["code"] != null && Request.QueryString["error"] != "access_denied")
{
// If I got code and no error then
// ask for access_code so I can get user email
//Here I ask for the access_code.
WebRequest requestLogIn = null;
Stream stream = null;
WebResponse response = null;
StreamReader reader = null;
string sendData = "code=" + Request.QueryString["code"] + "&";
sendData += "client_id=" + ObtenerClientID() + "&";
sendData += "client_secret=" + ObtenerClientSecret() + "&";
sendData += "redirect_uri=" + System.Configuration.ConfigurationManager.AppSettings["urlLogin"] + "&"; //TODO: ver si es necesario
sendData += "grant_type=authorization_code";
requestLogIn = WebRequest.Create("https://accounts.google.com/o/oauth2/token");
requestLogIn.Method = "POST";
requestLogIn.ContentType = "application/x-www-form-urlencoded";
byte[] arrayToSend = Encoding.UTF8.GetBytes(sendData);
requestLogIn.ContentLength = arrayToSend.Length;
stream = requestLogIn.GetRequestStream();
stream.Write(arrayToSend, 0, arrayToSend.Length);
stream.Close();
response = requestLogIn.GetResponse();
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.OK)
{
stream = response.GetResponseStream();
reader = new StreamReader(stream);
string responseValue = reader.ReadToEnd();
reader.Close();
var lJSONResponse = new JavaScriptSerializer().Deserialize<JSONResponseToken>(responseValue);
//Now that I have the access_code ask for the user email so I can match him in my base and load claims.
WebRequest myRequest = WebRequest.Create("https://www.googleapis.com/oauth2/v2/userinfo");
myRequest.Method = "GET";
myRequest.Headers.Add("Authorization", "Bearer " + lJSONResponse.Access_Token);
response = myRequest.GetResponse();
if (((HttpWebResponse)response).StatusCode == HttpStatusCode.OK)
{
stream = response.GetResponseStream();
reader = new StreamReader(stream);
responseValue = reader.ReadToEnd();
var lUserMail = new JavaScriptSerializer().Deserialize<JSONResponseUserMail>(responseValue);
// User is authenticated
FormsAuthentication.SetAuthCookie(lUserMail.Email, false);
// default.aspx will load claims
Response.Redirect("default.aspx?" + Request.QueryString.ToString());
}
}
}
else
{
//redirect to google for login.
//Save original url in a cookie for later use.
Guid lGuid = Guid.NewGuid();
CreateContextCookie(lGuid.ToString(), this.Request.Url.AbsoluteUri);
Response.Redirect(
"https://accounts.google.com/o/oauth2/auth?" +
"response_type=code&" +
"client_id=" + ObtenerClientID() + "&" +
//I want to return here again
"redirect_uri=" + HttpUtility.UrlEncode(System.Configuration.ConfigurationManager.AppSettings["urlLogin"]) + "&" +
//Add scope so I can get user mail.
"scope=" + HttpUtility.UrlEncode("https://www.googleapis.com/auth/userinfo.email") + "&" +
//Reference to the cookie so I can get the original url again
"state=" + HttpUtility.UrlEncode(lGuid.ToString())
);
}
}
Default.aspx.cs:
protected void Page_PreRender(object sender, EventArgs e) {
String lCode = Request.QueryString["code"];
String lSTate = Request.QueryString["state"];
var ctxCookie = this.Request.Cookies[lSTate];
var requestMessage = (SignInRequestMessage)WSFederationMessage.CreateFromUri(new Uri(ctxCookie.Value));
//Erase cookie
var contextCookie = new HttpCookie(lSTate)
{
Expires = DateTime.UtcNow.AddDays(-1)
};
//process login request
SecurityTokenService sts =
new CustomSecurityTokenService(CustomSecurityTokenServiceConfiguration.Current);
SignInResponseMessage responseMessage =
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInRequest(requestMessage, this.User, sts);
FederatedPassiveSecurityTokenServiceOperations.ProcessSignInResponse(responseMessage, this.Response);
this.Response.Cookies.Add(contextCookie);
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.