You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@esme.apache.org by Richard Hirsch <hi...@gmail.com> on 2010/01/08 13:32:36 UTC

Container-based authentication

Been thinking a lot about container based authentication - primarily,
because of my interest in the CAS integration which is necessary for
an OFBiz integration (search for OFBizCasAuthenticationHandler.java
class for details)

Here a few thoughts.

in J2EE, the way to get the user is via the following code:

 java.security.Principal principal = request.getUserPrincipal();
    if(principal != null) {
        String username = principal.getName();
        // usw. usf.
    }

If we used the UserPwdAuthModule in UserAuth.scala as a basis, we
could use the following code combined with the code above to get the
user:

            user <- UserAuth.find(By(UserAuth.authKey, name),
                                  By(UserAuth.authType,
moduleName)).flatMap(_.user.obj) or
            User.find(By(User.nickname, name))

We could take use the S object in lift to get the request and then get
the UserPrincipal.  Probably with "S.request"

The only I don't know is how to make this Container-based authmodule
be the default that works without a UI that implicitly calls it.

One idea is to remove  the following lines from Boot.scala
    UserAuth.register(UserPwdAuthModule)
    UserAuth.register(OpenIDAuthModule)

and replace them with
   UserAuth.register(ContaionerAuthModule)


Anyone have any ideas / thoughts?

D.

Re: Container-based authentication

Posted by Richard Hirsch <hi...@gmail.com>.
On Sun, Jan 10, 2010 at 9:48 AM, Vassil Dichev <vd...@apache.org> wrote:
>> Played further with the Container-based AuthModule and got a little
>> farther. Can't compile the code based on my limited Scala knowledge
>> but I hope you see what I'm trying to achieve.
>
> OK, baby steps.

First attempt.

>
>> You'll notice that I left the ModuleName with "upw". I've done this,
>> because I'd assume that the api2 could be used to create the users. A
>> moduleName with "container" wouldn't make much sense.
>>
>> I also don't know what do do with "case Req("authentication" ::
>> "login" :: Nil, _, PostRequest) =>", because it refers to a specific
>> login page which we won't have if had container-based authentication.
>
> Maybe the ifLoggedIn function in the *Mgr.scala would redirect to this
> page on first request, which would then redirect back after
> initializing the session.
>
>> Maybe someon can give me a tip where my Scala mistakes are....
>>
>> object ContainerAuthModule extends AuthModule {
>>
>>  def moduleName: String = "upw"
>
> While this is correct, the return value doesn't change, so you can use
> a val instead of def. You can also safely skip the String declaration
> and let the compiler infer the type of the result. For more
> complicated return values, you could annotate the type for
> documentation and a bit of extra assurance.
>
>>  def performInit(): Unit = {
>>    LiftRules.dispatch.append {
>>      case Req("authentication" :: "login" :: Nil, _, PostRequest) =>
>>        val from = S.referer openOr "/"
>>
>>        (for {
>>            java.security.Principal principal = S.Request.getUserPrincipal();
>>            if(principal != null) {
>>                 String username = principal.getName();
>>
>>                  user <- UserAuth.find(By(UserAuth.authKey, username),
>>                                  By(UserAuth.authType,
>> moduleName)).flatMap(_.user.obj) or
>>                  User.find(By(User.nickname, username))
>>
>>                  userAuth <- UserAuth.find(By(UserAuth.user,
>> username), By(UserAuth.authType, moduleName))
>>            }
>>            if true
>>          } yield user) match {
>>          case Full(user) =>
>>            User.logUserIn(user)
>>            S.notice(S.?("base_user_msg_welcome", user.niceName))
>>
>>          case _ =>
>>            S.error(S.?("base_user_err_unknown_creds"))
>>        }
>>
>>        S.redirectTo(from)
>>    }
>>  }
>
> It seems the big problem here is the "for" statement. What seems weird is this:
>
>    if true
>  } yield user
>

That was just an attempt - based on original userpassword authmodule
where the authentication is checked and I didn't think of an
appropriate method, so I just used "true"

> For comprehensions are not entirely like the Java for loop and yield
> is not like return. It is more like a value to be returned for each of
> the elements in the collection. Note that an Option or Box type can
> also be viewed as a collection of zero or one elements, and using
> these is more idiomatic than using an "if" filter (but this is a huge
> topic in itself). This seems to be an informative article about "for"
> comprehensions I found:
>
> http://creativekarma.com/ee.php/weblog/comments/the_scala_for_comprehension_from_a_java_perspective/
>
> Perhaps the best way would be to learn by example and show a more
> "best practice" code. Let me try this later.
>

Re: Container-based authentication

Posted by Vassil Dichev <vd...@apache.org>.
> Played further with the Container-based AuthModule and got a little
> farther. Can't compile the code based on my limited Scala knowledge
> but I hope you see what I'm trying to achieve.

OK, baby steps.

> You'll notice that I left the ModuleName with "upw". I've done this,
> because I'd assume that the api2 could be used to create the users. A
> moduleName with "container" wouldn't make much sense.
>
> I also don't know what do do with "case Req("authentication" ::
> "login" :: Nil, _, PostRequest) =>", because it refers to a specific
> login page which we won't have if had container-based authentication.

Maybe the ifLoggedIn function in the *Mgr.scala would redirect to this
page on first request, which would then redirect back after
initializing the session.

> Maybe someon can give me a tip where my Scala mistakes are....
>
> object ContainerAuthModule extends AuthModule {
>
>  def moduleName: String = "upw"

While this is correct, the return value doesn't change, so you can use
a val instead of def. You can also safely skip the String declaration
and let the compiler infer the type of the result. For more
complicated return values, you could annotate the type for
documentation and a bit of extra assurance.

>  def performInit(): Unit = {
>    LiftRules.dispatch.append {
>      case Req("authentication" :: "login" :: Nil, _, PostRequest) =>
>        val from = S.referer openOr "/"
>
>        (for {
>            java.security.Principal principal = S.Request.getUserPrincipal();
>            if(principal != null) {
>                 String username = principal.getName();
>
>                  user <- UserAuth.find(By(UserAuth.authKey, username),
>                                  By(UserAuth.authType,
> moduleName)).flatMap(_.user.obj) or
>                  User.find(By(User.nickname, username))
>
>                  userAuth <- UserAuth.find(By(UserAuth.user,
> username), By(UserAuth.authType, moduleName))
>            }
>            if true
>          } yield user) match {
>          case Full(user) =>
>            User.logUserIn(user)
>            S.notice(S.?("base_user_msg_welcome", user.niceName))
>
>          case _ =>
>            S.error(S.?("base_user_err_unknown_creds"))
>        }
>
>        S.redirectTo(from)
>    }
>  }

It seems the big problem here is the "for" statement. What seems weird is this:

    if true
  } yield user

For comprehensions are not entirely like the Java for loop and yield
is not like return. It is more like a value to be returned for each of
the elements in the collection. Note that an Option or Box type can
also be viewed as a collection of zero or one elements, and using
these is more idiomatic than using an "if" filter (but this is a huge
topic in itself). This seems to be an informative article about "for"
comprehensions I found:

http://creativekarma.com/ee.php/weblog/comments/the_scala_for_comprehension_from_a_java_perspective/

Perhaps the best way would be to learn by example and show a more
"best practice" code. Let me try this later.

Re: Container-based authentication

Posted by Richard Hirsch <hi...@gmail.com>.
Played further with the Container-based AuthModule and got a little
farther. Can't compile the code based on my limited Scala knowledge
but I hope you see what I'm trying to achieve.

You'll notice that I left the ModuleName with "upw". I've done this,
because I'd assume that the api2 could be used to create the users. A
moduleName with "container" wouldn't make much sense.

I also don't know what do do with "case Req("authentication" ::
"login" :: Nil, _, PostRequest) =>", because it refers to a specific
login page which we won't have if had container-based authentication.

Maybe someon can give me a tip where my Scala mistakes are....

object ContainerAuthModule extends AuthModule {

  def moduleName: String = "upw"

  def performInit(): Unit = {
    LiftRules.dispatch.append {
      case Req("authentication" :: "login" :: Nil, _, PostRequest) =>
        val from = S.referer openOr "/"

        (for {
            java.security.Principal principal = S.Request.getUserPrincipal();
            if(principal != null) {
                 String username = principal.getName();

                  user <- UserAuth.find(By(UserAuth.authKey, username),
                                  By(UserAuth.authType,
moduleName)).flatMap(_.user.obj) or
                  User.find(By(User.nickname, username))

                  userAuth <- UserAuth.find(By(UserAuth.user,
username), By(UserAuth.authType, moduleName))
            }
            if true
          } yield user) match {
          case Full(user) =>
            User.logUserIn(user)
            S.notice(S.?("base_user_msg_welcome", user.niceName))

          case _ =>
            S.error(S.?("base_user_err_unknown_creds"))
        }

        S.redirectTo(from)
    }
  }


On Fri, Jan 8, 2010 at 4:12 PM, Richard Hirsch <hi...@gmail.com> wrote:
> On Fri, Jan 8, 2010 at 3:38 PM, Daniel Koller <da...@googlemail.com> wrote:
>> ...only a short remark: that would also ease the task to enable Win NT
>> authentication. (because NT auth is then just a matter of container
>> configuration).
>> AFAIK there recipes already how to make it work on Tomcat.
>>
>> However we should look what this means for the task of role management.
>
> We are waiting for LDAP to come to Lift before moving more in this
> direction. But you might also want to take a look at Ethan's work
> regarding the admin role. In the threads discussing his work, we also
> talked about groups / roles...
>>
>> Kind regards,
>>
>> Daniel
>>
>> 8. Jan 2010 1:33 nachm. schrieb am "Richard Hirsch" <hi...@gmail.com>:
>>
>> Been thinking a lot about container based authentication - primarily,
>> because of my interest in the CAS integration which is necessary for
>> an OFBiz integration (search for OFBizCasAuthenticationHandler.java
>> class for details)
>>
>> Here a few thoughts.
>>
>> in J2EE, the way to get the user is via the following code:
>>
>>  java.security.Principal principal = request.getUserPrincipal();
>>   if(principal != null) {
>>       String username = principal.getName();
>>       // usw. usf.
>>   }
>>
>> If we used the UserPwdAuthModule in UserAuth.scala as a basis, we
>> could use the following code combined with the code above to get the
>> user:
>>
>>           user <- UserAuth.find(By(UserAuth.authKey, name),
>>                                 By(UserAuth.authType,
>> moduleName)).flatMap(_.user.obj) or
>>           User.find(By(User.nickname, name))
>>
>> We could take use the S object in lift to get the request and then get
>> the UserPrincipal.  Probably with "S.request"
>>
>> The only I don't know is how to make this Container-based authmodule
>> be the default that works without a UI that implicitly calls it.
>>
>> One idea is to remove  the following lines from Boot.scala
>>   UserAuth.register(UserPwdAuthModule)
>>   UserAuth.register(OpenIDAuthModule)
>>
>> and replace them with
>>  UserAuth.register(ContaionerAuthModule)
>>
>>
>> Anyone have any ideas / thoughts?
>>
>> D.
>>
>

Re: Container-based authentication

Posted by Richard Hirsch <hi...@gmail.com>.
On Fri, Jan 8, 2010 at 3:38 PM, Daniel Koller <da...@googlemail.com> wrote:
> ...only a short remark: that would also ease the task to enable Win NT
> authentication. (because NT auth is then just a matter of container
> configuration).
> AFAIK there recipes already how to make it work on Tomcat.
>
> However we should look what this means for the task of role management.

We are waiting for LDAP to come to Lift before moving more in this
direction. But you might also want to take a look at Ethan's work
regarding the admin role. In the threads discussing his work, we also
talked about groups / roles...
>
> Kind regards,
>
> Daniel
>
> 8. Jan 2010 1:33 nachm. schrieb am "Richard Hirsch" <hi...@gmail.com>:
>
> Been thinking a lot about container based authentication - primarily,
> because of my interest in the CAS integration which is necessary for
> an OFBiz integration (search for OFBizCasAuthenticationHandler.java
> class for details)
>
> Here a few thoughts.
>
> in J2EE, the way to get the user is via the following code:
>
>  java.security.Principal principal = request.getUserPrincipal();
>   if(principal != null) {
>       String username = principal.getName();
>       // usw. usf.
>   }
>
> If we used the UserPwdAuthModule in UserAuth.scala as a basis, we
> could use the following code combined with the code above to get the
> user:
>
>           user <- UserAuth.find(By(UserAuth.authKey, name),
>                                 By(UserAuth.authType,
> moduleName)).flatMap(_.user.obj) or
>           User.find(By(User.nickname, name))
>
> We could take use the S object in lift to get the request and then get
> the UserPrincipal.  Probably with "S.request"
>
> The only I don't know is how to make this Container-based authmodule
> be the default that works without a UI that implicitly calls it.
>
> One idea is to remove  the following lines from Boot.scala
>   UserAuth.register(UserPwdAuthModule)
>   UserAuth.register(OpenIDAuthModule)
>
> and replace them with
>  UserAuth.register(ContaionerAuthModule)
>
>
> Anyone have any ideas / thoughts?
>
> D.
>

Re: Container-based authentication

Posted by Daniel Koller <da...@googlemail.com>.
...only a short remark: that would also ease the task to enable Win NT
authentication. (because NT auth is then just a matter of container
configuration).
AFAIK there recipes already how to make it work on Tomcat.

However we should look what this means for the task of role management.

Kind regards,

Daniel

8. Jan 2010 1:33 nachm. schrieb am "Richard Hirsch" <hi...@gmail.com>:

Been thinking a lot about container based authentication - primarily,
because of my interest in the CAS integration which is necessary for
an OFBiz integration (search for OFBizCasAuthenticationHandler.java
class for details)

Here a few thoughts.

in J2EE, the way to get the user is via the following code:

 java.security.Principal principal = request.getUserPrincipal();
   if(principal != null) {
       String username = principal.getName();
       // usw. usf.
   }

If we used the UserPwdAuthModule in UserAuth.scala as a basis, we
could use the following code combined with the code above to get the
user:

           user <- UserAuth.find(By(UserAuth.authKey, name),
                                 By(UserAuth.authType,
moduleName)).flatMap(_.user.obj) or
           User.find(By(User.nickname, name))

We could take use the S object in lift to get the request and then get
the UserPrincipal.  Probably with "S.request"

The only I don't know is how to make this Container-based authmodule
be the default that works without a UI that implicitly calls it.

One idea is to remove  the following lines from Boot.scala
   UserAuth.register(UserPwdAuthModule)
   UserAuth.register(OpenIDAuthModule)

and replace them with
  UserAuth.register(ContaionerAuthModule)


Anyone have any ideas / thoughts?

D.