I am creating a custom login page for a sharepoint forms based authentication.
The default page has a login control, and the login control has 2 methods, the signing in and the onauthorize.
The signin gets a userid, whera later I need it to verify the SMS with an external sms provider.
I tried to do this with Session but I get this error
Session state can only be used when enableSessionState is set to true,
either in a configuration file or in the Page directive. Please also
make sure that System.Web.SessionStateModule or a custom session state
module is included in the \\
section in the application configuration.
Code
namespace Authentication.FBA2FA.CustomLogin.Layouts.Authentication.FBA2FA.CustomLogin
{
public partial class CustomLoginPage : FormsSignInPage
{
private string cellnumber;
private bool siCell;
AuthyClient client;
private string useridAuthy;
protected void Page_Load(object sender, EventArgs e)
{
}
protected void signInControl_Authenticate(object sender, AuthenticateEventArgs e)
{
SecurityToken token = null;
LoginControl formsLoginControl = sender as LoginControl;
TextBox txtphone = (TextBox)signInControl.FindControl("tbxPhone");
TextBox txtSecureCode = (TextBox)signInControl.FindControl("tbxSecureCode");
client = GetAuthyClient();
// I need to get the user id here.
var tokenresult = client.VerifyToken(Session["userid"].ToString(), txtSecureCode.Text);
if (tokenresult.Status != AuthyStatus.Success)
{
siCell = true;
}
else
{
siCell = false;
}
//bSendSms.Click += bSendSms_Click;
if (null != (token = GetSecurityToken(formsLoginControl)))
{
if (siCell)
{
EstablishSessionWithToken(token);
e.Authenticated = true;
base.RedirectToSuccessUrl();
}
else
{
e.Authenticated = false;
}
}
}
//private void bSendSms_Click(object sender, EventArgs e)
//{
//}
private SPIisSettings IisSettings
{
get
{
SPWebApplication webApp = SPWebApplication.Lookup(new Uri(SPContext.Current.Web.Url));
SPIisSettings settings = webApp.IisSettings[SPUrlZone.Default];
return settings;
}
}
private SecurityToken GetSecurityToken(LoginControl formsLoginControl)
{
SecurityToken token = null;
SPIisSettings iisSettings = IisSettings;
Uri appliesTo = base.AppliesTo;
if (string.IsNullOrEmpty(formsLoginControl.UserName) || string.IsNullOrEmpty(formsLoginControl.Password))
return null;
SPFormsAuthenticationProvider authProvider = iisSettings.FormsClaimsAuthenticationProvider;
token = SPSecurityContext.SecurityTokenForFormsAuthentication(
appliesTo,
authProvider.MembershipProvider,
authProvider.RoleProvider,
formsLoginControl.UserName,
formsLoginControl.Password);
return token;
}
protected void btnSms_Click(object sender, EventArgs e)
{
TextBox txtSecureCode = (TextBox)signInControl.FindControl("tbxSecureCode");
TextBox txtphone = (TextBox)signInControl.FindControl("tbxPhone");
int n;
bool isNumeric = int.TryParse(txtphone.Text, out n);
if (string.IsNullOrEmpty(txtphone.Text) && !isNumeric)
{
ClaimsFormsPageMessage.Text = "Please insert a cellphone number";
}
else
{
cellnumber = txtphone.Text;
client = GetAuthyClient();
var result = client.RegisterUser("univer.diego.s#gmail.com", cellnumber, 57);
useridAuthy = result.UserId;
// I need to set the user id here.
Session["userid"] = useridAuthy;
client.SendSms(result.UserId, true);
}
}
}
}
Because this is Sharepoint, I am not sure if I should do something in the web.config for the web application and if it will do any damage to sharepoint itself.
thanks a lot
Instead of modifying SharePoint's web.config file(s), you can just add EnableSessionState="True" to the Page directive on your custom page.
<%# Page Language="C#" EnableSessionState="True" ... %>
Related
I'm doing a session ID change, but when it redirects to the Default.aspx page it loses all the keys I assigned to it!
this strange, any clue or help?
Even when I'm commenting this part :
Session.Clear();
Session.Abandon();
Session.RemoveAll();
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
}
it loses everything!
Here is my code:
protected void btnDebugLogin_Click(object sender, EventArgs e)
{
try
{
string email = "test#123.com";
string pw = "password";
string ip = Request.UserHostAddress.ToString();
string browseragent = Request.UserAgent.ToString();
ConsoleUser loginUser = new ConsoleUser();
AbandonSession();//Delete any existing sessions
var newSessionId = CreateSessionId(HttpContext.Current); //Create a new SessionId
SetSessionId(HttpContext.Current, newSessionId);
loginUser = SecureLogin.Login(email, pw, ip, browseragent, referrer, LangCode, Session.SessionID.ToString(), null);
if (loginUser == null)
{
lblMsg.Visible = true;
}
else
{
Session["CurrentUser"] = loginUser;
Session["CurrentLoginID"] = loginUser.CurrentLoginId; // Used for tracking User Activity in KeepSessionAlive
Response.Redirect("/qConsole/Default.aspx",false);
}
}
catch(Exception ex)
{
}
}
protected void AbandonSession()
{
Session.Clear();
Session.Abandon();
Session.RemoveAll();
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Value = string.Empty;
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddMonths(-20);
}
if (Request.Cookies["__AntiXsrfToken"] != null)
{
Response.Cookies["__AntiXsrfToken"].Value = string.Empty;
Response.Cookies["__AntiXsrfToken"].Expires = DateTime.Now.AddMonths(-20);
}
}
private static string CreateSessionId(HttpContext httpContext)
{
var manager = new SessionIDManager();
string newSessionId = manager.CreateSessionID(httpContext);
return newSessionId;
}
public static void SetSessionId(HttpContext httpContext, string newSessionId)
{
var manager = new SessionIDManager();
bool redirected;
bool cookieAdded;
manager.SaveSessionID(httpContext, newSessionId, out redirected, out cookieAdded);
}
and the validation part is done in the Master Page before the Default.apsx page is loaded, here:
protected void Page_Init(object sender, EventArgs e)
{
if (Session["CurrentUser"] == null)
{
Response.Redirect("/");
}
// ..
}
This is the expected result of telling the client to use a new session id. The values are still in the old session, but there is no connection between the old one and the new one. The Session is attached to the request early on in the request cycle, and changing a cookie value during the handling won't affect what session is attached to the user's requests until the next request comes in. What you want to do is clear the cookie when you first render the page, not when they click the button. There are some other subtleties to session management that I mention in my answer https://stackoverflow.com/a/45383679/10558.
You've tagged this question csrf but your solution does nothing for that attack. What resetting the session id prevents is session fixation.
I'm creating a website to work with a game app where alliances can battle against one another.
This is my first attempt at a webpage and I'm trying to pass an ID to another page. The problem is that my page_load fires the first time and I set the ViewState variables but then my master page loads which causes everything to be reset.
First page:
FindOpponent.aspx (button click sets the ID and then proceeds to here)
Context.Items["WarID"] = tw.ID;
Server.Transfer("ConfirmWarTimer.aspx");
Second Page:
ConfirmWarTimer.aspx (Everything works the first time Page_Load gets called. ViewState contains my variable and timer is enabled)
protected void Page_load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
ActivateTimer();
return;
}
}
public void ActivateTimer()
{
if (!tim.Enabled)
{
DBClassesDataContext db = new DBClassesDataContext();
if (Context.Items["WarID"] != null)
{
ViewState["WarID"] = Context.Items["WarID"];
var thisWar = from a in db.tblWars where a.ID == int.Parse(ViewState["WarID"].ToString()) select a;
foreach (var a in thisWar)
{
TimeSpan t = TimeSpan.Parse(a.CountDown.ToString());
ViewState["Hours"] = t.Hours;
ViewState["Minutes"] = t.Minutes;
ViewState["Seconds"] = t.Seconds;
ViewState["TimeStamp"] = a.TimeStamp.ToString();
}
}
lblStart.Value = ViewState["TimeStamp"].ToString();
tim.Enabled = true;
return;
}
}
But then the master page init/preload/load get called. After that, the Page_Load gets called again on my second page but this time the Context.Items is blank and the ViewState is blank and the timer.enabled is false.
Master Page cs (This is just the page that was created with my project. I added the page_load so the menu wouldn't show on the default.aspx page.)
protected void Page_Init(object sender, EventArgs e)
{
// The code below helps to protect against XSRF attacks
var requestCookie = Request.Cookies[AntiXsrfTokenKey];
Guid requestCookieGuidValue;
if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
{
responseCookie.Secure = true;
}
Response.Cookies.Set(responseCookie);
}
Page.PreLoad += master_Page_PreLoad;
}
protected void master_Page_PreLoad(object sender, EventArgs e)
{
if (!IsPostBack)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}
protected void Page_Load(object sender, EventArgs e)
{
if ((Request.Url.ToString().ToLower().IndexOf("default") > -1))
{
pnMenu.Visible = false;
}
else
{
pnMenu.Visible = true;
}
}
protected void Unnamed_LoggingOut(object sender, LoginCancelEventArgs e)
{
Context.GetOwinContext().Authentication.SignOut();
}
I've tried to understand viewstate and when to set it and where but after many attempts and changes, viewstate never seems to stick around in my page.
How can I get the viewstate to persist on the second page (ConfirmWarTimer.aspx) after my masterpage 'loads' have executed?
This question already has answers here:
Facebook JS SDK's FB.api('/me') method doesn't return the fields I expect in Graph API v2.4+
(4 answers)
Closed 7 years ago.
I am trying to access user's information through a Facebook Login page in my WinForm application. Even though I ask for user's email in extended permissions, all I get after submit is the name and the id.
public partial class Form1 : Form
{
private const string AppId = "MY_APP_ID_IS_HERE";
private Uri loginUrl;
private const string extendedPermissions = "public_profile,user_friends,email";
FacebookClient fbClient = new FacebookClient();
private string _accessToken;
private bool _authorized;
private string _currentName;
private string _currentEmail;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Login();
}
private void Login()
{
dynamic parameters = new ExpandoObject();
parameters.client_id = AppId;
parameters.redirect_uri = "https://www.facebook.com/connect/login_success.html";
parameters.response_type = "token";
parameters.display = "popup";
if (!string.IsNullOrWhiteSpace(extendedPermissions))
parameters.scope = extendedPermissions;
var fb = new FacebookClient();
loginUrl = fb.GetLoginUrl(parameters);
webBrowser1.Navigate(loginUrl.AbsoluteUri);
}
private void webBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
if (webBrowser1.Visible)
{
var fb = new FacebookClient();
FacebookOAuthResult oauthResult;
if (fb.TryParseOAuthCallbackUrl(e.Url, out oauthResult))
{
if (oauthResult.IsSuccess)
{
_accessToken = oauthResult.AccessToken;
_authorized = true;
}
else
{
_accessToken = "";
_authorized = false;
}
if (_authorized)
{
fb = new FacebookClient(_accessToken);
dynamic result = fb.Get("me");
_currentName = result.name;
_currentEmail = result.email;
lblLoggedInUser.Text = string.Format("Facebook User: {0}", _currentName);
lblPassword.Text = string.Format("Email: {0}", _currentEmail);
//Do what need being done now that we are logged in!
}
else
{
MessageBox.Show("Couldn't log into Facebook!", "Login unsuccessful", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
}
}
When I run the query and ask for the user's email using Facebook Graph API Explorer, it returns this debug message:
Apparently my program is not asking for permission to use user's email. Because immediately after I submit my login a white page with the text "Success" is shown and no value for email is returned.
How can I change my login page to ask for user's email?
Try
dynamic result = fb.Get("me?fields=id,name,email");
I have the following code in my Global.asax
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (HttpContext.Current.Handler is IRequiresSessionState)
{
if (Request.IsAuthenticated)
{
if (HttpContext.Current.Session[this.MemberShipProvider.PrincipalSessionKey] != null)
{
CxPrincipal principal;
try
{
principal = (CxPrincipal)HttpContext.Current.Session[this.MemberShipProvider.PrincipalSessionKey];
}
catch
{
principal = null;
}
HttpContext.Current.User = principal;
Thread.CurrentPrincipal = principal;
}
else
{
var identity = new CxIdentity("admin", 1, "", true);
CxPrincipal principalLogin = new CxPrincipal(identity, 1);
HttpContext.Current.Session[this.MemberShipProvider.PrincipalSessionKey] = principalLogin;
HttpContext.Current.Session[SessionName.CurrentUser] = "Admin User";
HttpContext.Current.User = principalLogin;
Thread.CurrentPrincipal = principalLogin;
this.FormServiceProvider.SignIn("admin", false); // this is equal to FormsAuthentication.SetAuthCookie
}
}
}
}
The problem is that everytime the Session is object is null. Not only here, I can't use sessions in my application as well. Either the session is being Reset or something like that.
My application doesn't require the user to Login anymore. Therefore I am not using Session.Clear or Session.Abandon any where in my application.
Please help me, why is my session variable not setting?
You need to implement (and m.b. leave empty) 2 methods in your global.asax.cs:
void Session_Start(object sender, EventArgs e)
{
}
void Session_End(object sender, EventArgs e)
{
}
I am trying to authenticate a user on Facebook using the Facebook C# SDK on Windows Phone 8. To do so I am following the code here: FacebookLoginPage.xaml.cs
But the problem I am facing is that, whenever I input my username and password into the dialog that opens to authenticate the user, I just get the following page:
After this, my program does not redirect to the Landing page which is a separate view. The other solutions I have seen that suggest hiding the WebView are not applicable since the authentication is abstracted into a single LoginAsync function call.
Any suggestions on what to do?
It would seem that FB has made some changes to its redirection script, when it detects a Windows Phone webbrowser control.
What the C# SDK does, is generate the login page as "http://www.facebook.com....". When you open this URL on the webbrowser control, it gets redirected to "http://m.facebook.com..." which displays the mobile version of the FB login page.
This previously has no issue, but recently, when FB does the redirection, it also strips the parameter "display=page" from the URL. What happens then is that when a successful FB login is made, the "login_success.html" page is opened without this parameter. Without the "display=page" parameter passed in, it defaults to "display=touch". This URL unfortunately, does not append the token string in the URL, hence the page shown in the very first thread is displayed.
The solution to this is, instead of using the below code to generate the login URL, ammend it to
original:
Browser.Navigate(_fb.GetLoginUrl(parameters));
ammended:
var URI = _fb.GetLoginUrl(parameters).toString().replace("www.facebook.com","m.facebook.com");
Browser.Navigate(new Uri(URI));
In my project I just listened for the WebView's navigated event. If it happens, it means that user did something on the login page (i.e. pressed login button).
Then I parsed the uri of the page you mentioned which should contain OAuth callback url, if it is correct and the result is success I redirect manually to the correct page:
//somewhere in the app
private readonly FacebookClient _fb = new FacebookClient();
private void webBrowser1_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
FacebookOAuthResult oauthResult;
if (!_fb.TryParseOAuthCallbackUrl(e.Uri, out oauthResult))
{
return;
}
if (oauthResult.IsSuccess)
{
var accessToken = oauthResult.AccessToken;
//you have an access token, you can proceed further
FBLoginSucceded(accessToken);
}
else
{
// errors when logging in
MessageBox.Show(oauthResult.ErrorDescription);
}
}
If you abstract logging in an async function, you expect it to behave asynchronously, so events are ok.
Sorry for my English.
The code for the full page:
public partial class LoginPageFacebook : PhoneApplicationPage
{
private readonly string AppId = Constants.FacebookAppId;
private const string ExtendedPermissions = "user_birthday,email,user_photos";
private readonly FacebookClient _fb = new FacebookClient();
private Dictionary<string, object> facebookData = new Dictionary<string, object>();
UserIdentity userIdentity = App.Current.Resources["userIdentity"] as UserIdentity;
public LoginPageFacebook()
{
InitializeComponent();
}
private void webBrowser1_Loaded(object sender, RoutedEventArgs e)
{
var loginUrl = GetFacebookLoginUrl(AppId, ExtendedPermissions);
webBrowser1.Navigate(loginUrl);
}
private Uri GetFacebookLoginUrl(string appId, string extendedPermissions)
{
var parameters = new Dictionary<string, object>();
parameters["client_id"] = appId;
parameters["redirect_uri"] = "https://www.facebook.com/connect/login_success.html";
parameters["response_type"] = "token";
parameters["display"] = "touch";
// add the 'scope' only if we have extendedPermissions.
if (!string.IsNullOrEmpty(extendedPermissions))
{
// A comma-delimited list of permissions
parameters["scope"] = extendedPermissions;
}
return _fb.GetLoginUrl(parameters);
}
private void webBrowser1_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
if (waitPanel.Visibility == Visibility.Visible)
{
waitPanel.Visibility = Visibility.Collapsed;
webBrowser1.Visibility = Visibility.Visible;
}
FacebookOAuthResult oauthResult;
if (!_fb.TryParseOAuthCallbackUrl(e.Uri, out oauthResult))
{
return;
}
if (oauthResult.IsSuccess)
{
var accessToken = oauthResult.AccessToken;
FBLoginSucceded(accessToken);
}
else
{
// user cancelled
MessageBox.Show(oauthResult.ErrorDescription);
}
}
private void FBLoginSucceded(string accessToken)
{
var fb = new FacebookClient(accessToken);
fb.GetCompleted += (o, e) =>
{
if (e.Error != null)
{
Dispatcher.BeginInvoke(() => MessageBox.Show(e.Error.Message));
return;
}
var result = (IDictionary<string, object>)e.GetResultData();
var id = (string)result["id"];
userIdentity.FBAccessToken = accessToken;
userIdentity.FBID = id;
facebookData["Name"] = result["first_name"];
facebookData["Surname"] = result["last_name"];
facebookData["Email"] = result["email"];
facebookData["Birthday"] = DateTime.Parse((string)result["birthday"]);
facebookData["Country"] = result["locale"];
Dispatcher.BeginInvoke(() =>
{
BitmapImage profilePicture = new BitmapImage(new Uri(string.Format("https://graph.facebook.com/{0}/picture?type={1}&access_token={2}", id, "square", accessToken)));
facebookData["ProfilePicture"] = profilePicture;
userIdentity.FBData = facebookData;
userIdentity.ProfilePicture = profilePicture;
ARLoginOrRegister();
});
};
fb.GetAsync("me");
}
private void ARLoginOrRegister()
{
WebService.ARServiceClient client = new WebService.ARServiceClient();
client.GetUserCompleted += client_GetUserCompleted;
client.GetUserAsync((string)facebookData["Email"]);
client.CloseAsync();
}
void client_GetUserCompleted(object sender, WebService.GetUserCompletedEventArgs e)
{
if (e.Result == null)
NavigationService.Navigate(new Uri("/RegisterPageFacebook.xaml", UriKind.RelativeOrAbsolute));
else if (e.Result.AccountType != (int)AccountType.Facebook)
{
MessageBox.Show("This account is not registered with facebook!");
NavigationService.Navigate(new Uri("/LoginPage.xaml", UriKind.RelativeOrAbsolute));
}
else
{
userIdentity.Authenticated += userIdentity_Authenticated;
userIdentity.FetchARSocialData((string)facebookData["Email"]);
}
}
void userIdentity_Authenticated(bool success)
{
NavigationService.Navigate(new Uri("/MenuPage.xaml", UriKind.RelativeOrAbsolute));
}
}
Before trying to do all the proposed changes,
please check that your Facebook App is not on Sandbox mode. This will eventually resolve your issue.
If your facebook app is in sandbox mode, only the developer can login, using his email address. Any other fb user will get the white page.