YAFLogo

ebirbal
  • ebirbal
  • 51.8% (Neutral)
  • YAF Forumling Topic Starter
14 years ago
I am brand new to YAF, and love it! Its a great piece of work!

I had to integrate YAF with my existing application that already used ASP .Net membership. I checked other forum posts on the subject and also the Wiki articles, and it seems to me that they are a bit dated and not compatible with the new provider model based authentication, so I rolled my own.

My approach basically involves creating a web service to handle authentication and user creation. I chose this approach because I wanted to keep YAF separate from my application (much easier to upgrade), yet wanted users to have a seamless experience between the two applications. With this approach, the forums would be hosted in a separate sub domain.

Step 1:

Generate a machine key for yourself from here  or here  and update the web.config in both your applications.

Step 2:

Open YAF solution in Visual Studio and create a new folder under YetAnotherForum.Net website. Within this folder, create a new Web Service, with the name YafMembership.asmx. Paste the code from the attached file YafMembership.cs into it.

Step 3:

In your main application, add a web reference to this newly created web service with the name 'Forums'

Note1: be sure to add a web reference and not a service reference.

Note2: depending of whether your main application is a web project or a website, the actual process of adding a web reference might vary a little - please check MSDN for help)

Step 4:

In your main application, paste the following code where you authenticate your user. This code should follow after you have authenticated the user. You will have to modify this code (especially the parts enclosed with

[h]attributes[/h][/code]) so that its relevant to your application.

    [code]bool CreateForumsTicket = false;

    Forums.AuthHeader AuthHeader = new Forums.AuthHeader();
    AuthHeader.SecretKey = FormsAuthentication.HashPasswordForStoringInConfigFile([h]UserName[/h], "md5");

    Forums.YafMembership Forums = new Forums.YafMembership();
    Forums.AuthHeaderValue = AuthHeader;

    if (Forums.Login([h]UserName[/h], [h]Password[/h]))
    {
        CreateForumsTicket = true;
    }
    else
    {
        [h]MembershipUser user = Membership.GetUser(UserName);
        Forums.MembershipCreateStatus Status = Forums.CreateUser(UserName, Password, UserEmail, PasswordQuestion, PasswordAnswer) ;[/h]
        if (Status == Forums.MembershipCreateStatus.Success)
            CreateForumsTicket = true;
        else{
            [h]// Add the code to log the failure using whatever error logging mechanism you use[/h]
        }
    }

    if (CreateForumsTicket)
    {
        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, UserName, DateTime.Now, DateTime.Now.AddMinutes(30), false, "", "/");
        string strEncTicket = FormsAuthentication.Encrypt(ticket);
        HttpCookie authCookie = new HttpCookie(".YAFNET_Authentication", strEncTicket);
        authCookie.Path = "/";
        authCookie.Domain = [h]"YourDomain.com"[/h];
        HttpContext.Current.Response.Cookies.Add(authCookie);
    }

Step 5:

You might also want to add code similar to the above after you have created a new user in your application

Step 6 (optional):

In the Forums folder that you created in Step 2, create a web.config as shown below

<configuration>
  <system.web>
    <webServices>
      <protocols>
        <remove name="HttpPost" />
        <remove name="HttpGet" />
        <remove name="Documentation" />
        <add name="HttpPostLocalhost" />
      </protocols>
    </webServices>
  </system.web>
</configuration>
This web.config removes unnecessary protocols and documentation about the web service to prevent automatic sign ups. This is in addition to the hashed SecretKey exchanged in the web service header.

Note: if you ever need to re-generate the proxy class created in step 3, make sure you comment out the

<remove name="Documentation" />[/code] node in the above web.config.

🅱Step 7:[/b]
Go to the YAF admin area, Host Settings -> Login/Registration Settings and check 'Disable New Registrations'. This will prevent the 'Register' link from appearing. However, the user can still manually enter the registration URL and register - in order to prevent that, open YetAnotherForum.Net -> Pages -> Register.ascx.cs and in the Page_Load event redirect the user to the registration URL of your main site
[code]Response.Redirect([h]"YourDomain.com"[/h]);

Step 8:

Go to the YAF admin area, Host Settings -> Login/Registration Settings and modify 'Custom Login Redirect Url' so that users are directed to your main site for logging in.

That's about it.

(pauses)

You're welcome

Sponsor
Mertez
  • Mertez
  • 50.6% (Neutral)
  • YAF Forumling
13 years ago
Dears,

I am trying what you did in authenticating from outside of YAF. I have read your article many times and tried to do what every you told. but i think there are some differences between our YAF versions, i did some changes to bring up the application without errors but as long as i call YafMembership webservice i give an error for missing a parameter in SQL.

i tried to change your:

ForumPage currentPage = new ForumPage();

YafContext PageContext = currentPage.PageContext;

bool Result = PageContext.CurrentMembership.ValidateUser(UserName, Password);

To:

YAF.Providers.Membership.YafMembershipProvider ymp = new YAF.Providers.Membership.YafMembershipProvider();

bool Result = ymp.ValidateUser(UserName, Password);

in order to get rid of errors for FORUMPAGE() class. but now i'm giving the sql error below:

System.Data.SqlClient.SqlException: Procedure or function 'yaf_prov_getuser' expects parameter '@ApplicationName', which was not supplied.

i checked the source and found that the YAF.Providers.Membership.YafMembershipProvider.ValidateUser sends the @ApplicationName however it doesn't have it in parameters.

Now. do you have any idea? have you checked the problem in 1.9.5.5 ?

Morteza

mertez@gmail.com

ebirbal
  • ebirbal
  • 51.8% (Neutral)
  • YAF Forumling Topic Starter
13 years ago
Hey, sorry I am not a frequent visitor to the forums, and neither did I upgrade to 1.9.5, so i was not aware of this breaking change.

Anyways, I did decide to upgrade to 1.9.6 Beta and came across this issue myself. The fix though, is quiet simple really - all you need to get the current page context, is to use

YafContext.Current
So essentially, you can get rid of the following two lines:

ForumPage currentPage = new ForumPage();
YafContext PageContext = currentPage.PageContext;
and instead use YafContext.Current as appropriate

Please find the new YafMembership.cs attached. Its my guess that the above fix would work for 1.9.5 as well (but its just a guess)

Jaben and team, thanks for the awesome forums!

jigglypuff2
13 years ago
Thanks for this -- it got me on the right track...:)

I didn't need to add another cookie though -- with the same machine key, YAF picked up the creds of the user when they signed into my system.

jigglypuff2
13 years ago
I just realized -- there's no reason to even pass the password when calling the create new user in YAF, because the user never logs in from YAF.
jigglypuff2
13 years ago
Also, while hashin the username as a shared secret is clever, it seems a little overboard to me, since the service itself is pretty much hidden via security by obscurity. And, if you have captchka's turned on for posting messages, you'll prevent spam bots as it is.
jigglypuff2
13 years ago
As such, I've simplified your web service to this:


        [WebMethod]
        public bool IsUserRegistered(string UserName)
        {
            MembershipUser user;
            user = YafContext.Current.Get<MembershipProvider>().GetUser(UserName,false);
            if (user == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        [WebMethod]
        public MembershipCreateStatus CreateUser(string UserName, string Password, string email, string PasswordQuestion, string PasswordAnswer)
        {
            MembershipCreateStatus Status = MembershipCreateStatus.ProviderError;
            if (!IsUserRegistered(UserName))
            {
                YafContext.Current.Get<MembershipProvider>().CreateUser(UserName, Password, email, PasswordQuestion, PasswordAnswer, true, null, out Status);
                if (!RoleMembershipHelper.IsUserInRole(UserName, "Registered"))
                {
                    RoleMembershipHelper.AddUserToRole(UserName, "Registered");
                }
            }
            return Status;
        }

BTW, yeah for SOAP! :lol:

James H
  • James H
  • 50.6% (Neutral)
  • YAF Forumling
13 years ago
@jigglypuff2 - would it be possible to see the code you have implemented into your main application that authenticates via the web service with your new web service code?

Thanks in advance

jigglypuff2
12 years ago
Sure. I generate a proxy as explained earlier in the thread (funny that VS hides "Add Web Reference" now, but it's there as explained in the earlier thread.) Then, once I have the reference, this is all I do:


        Forums.YAFMembership Forums = new Forums.YAFMembership();
        if (!Forums.IsUserRegistered(login_control.UserName))
         {
             Forums.MembershipCreateStatus Status = Forums.CreateUser(login_control.UserName, "na", email, "na", "naa");

         }

jigglypuff2
12 years ago
Oh yeah, and don't forget to add the following to app.config


    <add key="YAF.AllowLoginAndLogoff" value="false" />