How to get email from Google OpenID Provider (in VB) - asp.net

Salam to all
I am using the DotNetOpenAuth control for authentication from google. This is the code that I am using.
<rp:OpenIdLogin ID="OID" runat=server Identifier="https://www.google.com/accounts/o8/id" RequestEmail="Require" ></rp:OpenIdLogin>
To get the response from the provider for the email ID I am using this code in the page load event of default.aspx
Public Email As String = "N/A"
Public FullName As String = "N/A"
Public Country As String = "N/A"
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim openid As OpenIdRelyingParty = New OpenIdRelyingParty
Dim response = openid.GetResponse
If (Not (response) Is Nothing) Then
Select Case (response.Status)
Case AuthenticationStatus.Authenticated
Dim fetch = response.GetExtension
Dim email As String = String.Empty
If (Not (fetch) Is Nothing) Then
email = fetch.GetAttributeValue(WellKnownAttributes.Contact.Email)
End If
FormsAuthentication.RedirectFromLoginPage(response.ClaimedIdentifier, False)
End Select
End If
End Sub
I am able be authenticated with google, but there is no response of the email id from google.
Please tell me what exactly I am missing that is causing this problem.
Update
<configSections>
<section name="dotNetOpenAuth" type="DotNetOpenAuth.Configuration.DotNetOpenAuthSection" requirePermission="false" allowLocation="true"/>
</configSections>
<dotNetOpenAuth>
<openid>
<relyingParty>
<behaviors>
<!-- The following OPTIONAL behavior allows RPs to use SREG only, but be compatible
with OPs that use Attribute Exchange (in various formats). -->
<add type="DotNetOpenAuth.OpenId.Behaviors.AXFetchAsSregTransform, DotNetOpenAuth" />
</behaviors>
</relyingParty>
</openid>
</dotNetOpenAuth>

You're likely missing the appropriate "behavior" in your web.config file. Please study this page and apply it to your site: https://github.com/DotNetOpenAuth/DotNetOpenAuth/wiki/Enhancements
Also, when using this behavior, you should be looking for the ClaimsResponse extension in the positive authentication response rather than FetchResponse.
As a side note, you have a lot of boilerplate code in your code-behind's Page_Load method that you don't need. The OpenIdControl you're using has a LoggedIn method that does most of what you're doing here (it gets you all the way to the body of your Case block.

Related

Access winform variable from browsercontrol

I have an application in ASP.Net Ajax. I want to open it via a browsercontrol from a winform, and I wish to access a variable (username) that the user used to log in to the webform with. On load I would like to read that username and perform the rest of my webpage code on that browsercontrol using that username.
My ASP.Net Ajax has been published to a internal web server and the browsercontrol loads that IP address.
Is there any way to achieve this at all?
EDIT:
I have discovered the javascript extension: window.external
And I can call a C# procedure from the webpage using javascript with it, which is a start, but I need to retrieve a varaible from c# - this is where the problem comes in. I have tried the
var name = function window.external.GetGlobalVariable(MyGlobalProcedure, "Cannot Get Value");
But javascript error says the method cannot be applied to the object.
Your answer should be as follows:
Public Class Form1
Dim GlobalVar As String = "Your Name"
Dim YourBrowser As New WebBrowser
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
YourBrowser.Url = New Uri("Your URL address")
AddHandler YourBrowser.DocumentCompleted, AddressOf PageLoadComplete
End Sub
'The invokescript will only work once the HTML has finished loading itself into your WebBrowser
Sub PageLoadComplete()
'Must declare the string inside an array as the invokescript only allows an object to be sent
Dim VarToSend As String() = {GlobalVar}
YourBrowser.Document.InvokeScript("yourJavascriptfunction", VarToSend)
End Sub
The javascript section should look as follows:
<script type="text/javascript" language="javascript">
function userNameSet(name) {
$(document).ready(function() {
//variable now exists inside your WebBrowser client and can be used accordingly now
alert(name);
});
}
</script>
References for answer: http://www.dotnetcurry.com/showarticle.aspx?ID=194
"Store that name in a session variable and access the session in your ajax call"
In your ASP.Net application create a hidden field (or if it's somewhere on the UI in some control that works also). Put the username or whatever information you want to share into that field.
From your WinForms program you can request that field through the WebBrowser control like this:
MessageBox.Show(WebBrowser1.Document.GetElementById("txtUsername").GetAttribute("value"))
The above assumes you have some HTML element called txtUsername with the value attribute set.

How to manitain session values during HttpWebRequest?

In my code I'm sending a HttpWebRequest to a page in my website.
When request sends to this page, It doesn't maintain the Session values.
Below is the code, from where I'm generating the web request:
Public Overloads Shared Function ReadURL(ByVal sUrl As String) As String
Dim sBody As String
Dim oResponse As HttpWebResponse
Dim oRequest As HttpWebRequest
Dim oCookies As New CookieContainer
oRequest = WebRequest.Create("http://localhost:64802/inventory/purchase_order.aspx?id=5654")
oRequest.CookieContainer = oCookies
oResponse = oRequest.GetResponse()
Dim oReader As New StreamReader(oResponse.GetResponseStream())
sBody = oReader.ReadToEnd
oReader.Close()
oResponse.Close()
Return sBody
End Function
Below is the code written on Page_Load of Purchaseorder.aspx.vb:
iDomains_ID = Session("Domains_ID")
iLogin_ID = Session("Login_ID")
sPage = Request.Path
If Request.QueryString.Count > 0 Then sPage &= "?" & Request.QueryString.ToString()
sPage = shared01.Encrypt(sPage, Application("PK"))
If Not User.Identity.IsAuthenticated Or iLogin_ID = 0 Then
Response.Redirect("/login.aspx?page=" & sPage)
Exit Sub
End If
Above code doesn't gets the session values and it redirects to the login page.
So, how i can maintain the session on both pages during HttpWebRequest.
Looking for your replies.
EDIT
I've tried to use CookieContainer class as you can see in above code. But it doesn't work at all.
As an alternative, assuming the calling and called pages are in the same application, you could use the Server.Execute method to load the content of the page without making a separate request to the site:
Public Overloads Function ReadURL(ByVal sUrl As String) As String
Using writer As New StringWriter()
Server.Execute("~/inventory/purchase_order.aspx?id=5654", writer, False)
Return writer.ToString()
End Using
End Function
If I've understood you correctly, you're making a request from one page in your site to another, and you want to send the cookies from the current HttpRequest with your WebRequest?
In that case, you'll need to manually copy the cookies to the CookieContainer:
For Each key As String In Request.Cookies.AllKeys
Dim sourceCookie As HttpCookie = Request.Cookies(key)
Dim destCookie As New Cookie(sourceCookie.Name, sourceCookie.Value, sourceCookie.Path, "localhost")
destCookie.Expires = sourceCookie.Expires
destCookie.HttpOnly = sourceCookie.HttpOnly
destCookie.Secure = sourceCookie.Secure
oCookies.Add(destCookie)
Next
NB: You'll either need to make the ReadUrl function non-Shared, or pass the current HttpRequest as a parameter.
You'll also need to make sure the calling page has EnableSessionState="false" in the <%# Page ... %> directive, otherwise the page you're calling will hang trying to obtain the session lock.
Your code seems like you will need to make a request and a post. The first request will redirect you to your login page. The second will be a request where you post to the login page, which will start the session and (?) store information into the session variables. That post (to the login page) will then redirect you to the page you want.
I used code in this example http://www.codeproject.com/Articles/145122/Fetching-ASP-NET-authenticated-page-with-HTTPWebRe (I tweaked it a bit) to write an application to do this.

.NET 4.0 FormsAuthentication.SetAuthCookie FAIL

I know there are a few questions out there on this already but none seem to help my problem.
I am debugging a VB.NET webForms app and I cannot Get FormsAuthentication.SetAuthCookie to work (with a non-persistent cookie). It seems to create an HttpContext.Current.User object when I check for it in a watch window it seems to have created the object, but not its "Identity" property.
I've read a bunch of SO posts checked the basic things, like seeing if my browser supports cookies, etc... This project is a direct port from an earlier project of ours, which uses the same code for all things listed here, and it works just fine, relatively speaking. Where this throws an exception is where it's called from my BLL code that is supposed to get it.
Here is the code that calls the FormsAuthentication method...:
'When participant logs in having already created records in DB.
Protected Sub btnGo_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles btnGo.Click
If Me.txtUsername.Text.Trim.Length <> 0 AndAlso Me.txtPassword.Text.Trim.Length <> 0 Then
If Membership.ValidateUser(Me.txtUsername.Text, Me.txtPassword.Text) Then
FormsAuthentication.SetAuthCookie(Me.txtUsername.Text, False)
'This is where we run into trouble; the property checks with the forms auth...
MyBLL.Common.CurrentUser = New MyBLL.User(Me.txtUsername.Text)
'set site property..
If Site_ IsNot Nothing Then
MyBLL.Common.CurrentUser.Site = Me.Site_
End If
MyBLL.Common.CurrentParticpant = Nothing
MyBLL.Common.CurrentParticpantVisitID = -1
Response.Redirect("~/Apps/Dashboard.aspx", True)
Else
Me.lblLoginMsg.Visible = True
End If
Else
Me.lblLoginMsg.Visible = True
End If
End Sub
Here is the code for the BLL object (which has a shared property calling user from HttpContext...)
Public Shared Property CurrentUser() As MyBLL.User
Get
Dim objUser As MyBLL.User
If Not IsNothing(HttpContext.Current.Session("currentSiteUser")) Then
objUser = CType(HttpContext.Current.Session("currentSiteUser"), MyBLL.User)
If objUser.Username <> HttpContext.Current.User.Identity.Name Then
objUser = New MyBLL.User(HttpContext.Current.User.Identity.Name)
HttpContext.Current.Session("currentSiteUser") = objUser
End If
Else
objUser = New MyBLL.User(HttpContext.Current.User.Identity.Name)
HttpContext.Current.Session("currentSiteUser") = objUser
End If
Return objUser
End Get
Set(ByVal value As MyBLL.User)
'_CurrentUser = value
HttpContext.Current.Session("currentSiteUser") = value
End Set
End Property
Here is the Forms element from my webConfig; everything seems alright here to me...
<authentication mode="Forms">
<forms loginUrl="~/Public/Default2.aspx" defaultUrl="~/Public/Default2.aspx" timeout="60"/>
</authentication>
You should immediately redirect after callaing the SetAuthCookie method and only on subsequent requests you may hope to get the full IPrincipal to be initialized. Do not try to access HttpContext.Current.User.Identity.Name in the same controller action in which you called the SetAuthCookie method. It won't have any effect. The redirect is important so that on the next request the forms authentication module will built the principal from the request cookie.
In your CurrentUser method you seem to be calling the HttpContext.Current.User.Identity.Name property but this is not available until you redirect.

MembershipProvider and RequiresQuestionAndAnswer

We provide a website template for our customers to use as the basis of their websites. Our website has a custom membership provider.
We have had a problem raised by one customer. The customer sends out invitations to prospective members by email with a url to login the member. During registration they set their security question / answer.
However sometimes the prospective member loses the email (and therefore their password) but still tries to join the site.
The customer requested that the member be allowed to reset their password without the usual security question / answer when registration was not complete.
Unfortunately the MembershipProvider doesn't provide the username when requesting whether the question / answer are required. However it does call GetUser() just before.
To get this feature working I added a method (StartingPasswordRecovery) to my MembershipProvider to flag that password reset was active, calling it from the OnVerifyingUser event in the PasswordRecovery page.
While this code works I'm not convinced that it's very robust.
Can anyone point me towards a better solution.
Here's the relevant code I added to my membership provider.
Private _hasUserDefinedQuestionAndAnswer As Boolean
Private _isResettingPassword As Boolean
Public Overloads Overrides Function GetUser(ByVal username As String, ByVal userIsOnline As Boolean) As System.Web.Security.MembershipUser
...
_hasUserDefinedQuestionAndAnswer = ...
...
End Function
Public Overrides ReadOnly Property RequiresQuestionAndAnswer() As Boolean
Get
If Me._isResettingPassword Then
Me._isResettingPassword = False
Return Me.pRequiresQuestionAndAnswer And Me._hasUserDefinedQuestionAndAnswer
End If
Return Me.pRequiresQuestionAndAnswer
End Get
End Property
Public Sub StartingPasswordRecovery()
Me._isResettingPassword = True
End Sub
I'm not sure if i've understood you correctly, but couldn't you use the User-Profile to determine if a user requires question and answer or not?
web.config:
<profile defaultProvider="YourProfileProvider">
<providers>
<clear/>
<add name="YourProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="ConnectionStringToDB" applicationName="/YourApp"></add>
</providers>
<properties>
<add name="RequiresQuestionAndAnswer" defaultValue="false" />
</properties>
</profile>
Custom membership-provider:
Public Overrides ReadOnly Property RequiresQuestionAndAnswer As Boolean
Get
If HttpContext.Current.User.Identity.IsAuthenticated Then
Dim userRequiresQuestionAndAnswer = _
CType(HttpContext.Current.Profile.GetPropertyValue("RequiresQuestionAndAnswer"), Boolean)
Return userRequiresQuestionAndAnswer
Else
Return MyBase.RequiresQuestionAndAnswer
End If
End Get
End Property
You could set it in your user-management page for every user individually:
HttpContext.Current.Profile.SetPropertyValue("RequiresQuestionAndAnswer", userRequiresQuestionAndAnswer)
HttpContext.Current.Profile.Save()
Edit:
according to your comment, i've modified the code a little bit. I hope that helps to get it working:
in custom membership-provider:
Public Overloads Overrides ReadOnly Property RequiresQuestionAndAnswer As Boolean
Get
If HttpContext.Current.User.Identity.IsAuthenticated Then
Return RequiresQuestionAndAnswer(Membership.GetUser.UserName)
Else
Return MyBase.RequiresQuestionAndAnswer
End If
End Get
End Property
Public Overloads ReadOnly Property RequiresQuestionAndAnswer(ByVal userName As String) As Boolean
Get
Dim profile As ProfileBase = ProfileBase.Create(userName)
If Not profile Is Nothing Then
Dim userRequiresQuestionAndAnswer = _
CType(profile.GetPropertyValue("RequiresQuestionAndAnswer"), Boolean)
Return userRequiresQuestionAndAnswer
Else
Return MyBase.RequiresQuestionAndAnswer
End If
End Get
End Property
where your PasswordRecovery-Control is:
Protected Sub VerifyingUser(ByVal sender As Object, ByVal e As LoginCancelEventArgs)
Dim login As WebControls.Login = DirectCast(Me.LoginView1.FindControl("Login1"), WebControls.Login)
Dim userName = DirectCast(login.FindControl("PwdRecovery"), PasswordRecovery).UserName
Dim RequiresQuestionAndAnswer = DirectCast(Membership.Provider, YourMembershipProvider).RequiresQuestionAndAnswer(userName)
'....'
End Sub

How can I use the URL to set the current culture in ASP.NET 2.0 Web App?

I am looking in to ways to enable a site to basically have something like:
http://mysite.com/en-US/index.aspx`
Where the "en-US" can vary by culture..
This culture in the URL will then basically set the CurrentUICulture for the application..
Basically, we currently have a page where the user explicitly clicks it, but some are favouriting past that, and it is causing some issues..
I know this sort of thing is easily done in ASP.NET MVC, but how about those of us still working in 2.0? Can you guys in all your wisdom offer any suggestions/pointers/ANYTHING that may get me started? This is new to me :)
I'm sure there must be some way to pick up the request and set/bounce as appropriate.. HttpModule maybe?
Update
Just had a thought.. May be best to create VirtDirs in IIS and then pull the appropriate part from the Requested URL and set the culture in InitializeCulture?
Is storing the choice in a cookie out of the question?
Nice of you to give the users a choice but why not just default to the users client/web browser settings?
If they bookmark a page and have lost the cookie you could fall back to the default and if that is a culture you do not support then fallback further to en-US.
If you want to keep your solution you could use a rewrite engine. I've used http://www.managedfusion.com/products/url-rewriter/ in the past. For a list of engines see http://en.wikipedia.org/wiki/Rewrite_engine#IIS
You can use the routing feature developed for MVC easily with webforms. This SO question addresses doing that:
ASP.NET Routing with Web Forms
If you can't use the 3.5 framework, there are a number of URL rewriting modules out there. I have no experience with any to be able to make a recommendation.
I'm doing it in some sites with ASP.net Routing.
Here is the code:
Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
' Code that runs on application startup
RegisterRoutes(RouteTable.Routes)
End Sub
Public Sub RegisterRoutes(ByVal routes As RouteCollection)
Dim reportRoute As Route
Dim DefaultLang As String = "es"
reportRoute = New Route("{lang}/{page}", New LangRouteHandler)
'* if you want, you can contrain the values
'reportRoute.Constraints = New RouteValueDictionary(New With {.lang = "[a-z]{2}"})
reportRoute.Defaults = New RouteValueDictionary(New With {.lang = DefaultLang, .page = "home"})
routes.Add(reportRoute)
End Sub
Then LangRouteHandler.vb class:
Public Class LangRouteHandler
Implements IRouteHandler
Public Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler _
Implements System.Web.Routing.IRouteHandler.GetHttpHandler
'Fill the context with the route data, just in case some page needs it
For Each value In requestContext.RouteData.Values
HttpContext.Current.Items(value.Key) = value.Value
Next
Dim VirtualPath As String
VirtualPath = "~/" + requestContext.RouteData.Values("page") + ".aspx"
Dim redirectPage As IHttpHandler
redirectPage = BuildManager.CreateInstanceFromVirtualPath(VirtualPath, GetType(Page))
Return redirectPage
End Function
End Class
Finally I use the default.aspx in the root to redirect to the default lang used in the browser list.
Maybe this can be done with the route.Defaults, but don't work inside Visual Studio (maybe it works in the server)
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim DefaultLang As String = "es"
Dim SupportedLangs As String() = {"en", "es"}
Dim BrowserLang As String = Mid(Request.UserLanguages(0).ToString(), 1, 2).ToLower
If SupportedLangs.Contains(BrowserLang) Then DefaultLang = BrowserLang
Response.Redirect(DefaultLang + "/")
End Sub
Some sources:
* Mike Ormond's blog
* Chris Cavanagh’s Blog
* MSDN
Just try to add that parameter
http://yoursite/yourPage.aspx?lang=en-US
If you were utilizing resources files it will work automatically.
Good Luck

Resources