cancel
Showing results for 
Search instead for 
Did you mean: 

Custom login module

former_member301120
Active Participant
0 Kudos
437

Hello to all,

I'm trying to develop a custom login modul. Now I did as described at http://help.sap.com/saphelp_nw04/helpdata/en/46/3ce9402f3f8031e10000000a1550b0/content.htm

But authentication always fails.

How can I read the provided user? Is it "user_name" or "j_user" as in the http-post?

Is it possible to debug the module? It is deployed as library and I don't know how to debug it.

Please advice

Regards Christian

Next my code:

package de.xy.ume;

import java.util.Map;

import java.io.IOException;

import javax.security.auth.login.LoginException;

import javax.security.auth.Subject;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.UnsupportedCallbackException;

import com.sap.engine.interfaces.security.auth.AbstractLoginModule;

import com.sap.engine.lib.security.http.HttpGetterCallback;

import com.sap.engine.lib.security.http.HttpCallback;

import com.sap.engine.lib.security.LoginExceptionDetails;

import com.sap.engine.lib.security.Principal;

public class FilterUsername extends AbstractLoginModule {

    // Define the variables that will be used later on:

    private CallbackHandler callbackHandler = null;

    private Subject subject = null;

    private Map sharedState = null;

    private Map options = null;

    // This is the name of the user you have created on

    // the J2EE Engine so you can test the login module

    private String userName = null;

    private boolean successful;

    private boolean nameSet;

    /**

     * The method initializes the login module with the

     * relevant authentication and state information.

     */

    public void initialize(

        Subject subject,

        CallbackHandler callbackHandler,

        Map sharedState,

        Map options) {

        // This is the only required step for the method

        super.initialize(subject, callbackHandler, sharedState, options);

        // Initializing the values of the variables

        this.callbackHandler = callbackHandler;

        this.subject = subject;

        this.sharedState = sharedState;

        this.options = options;

        this.successful = false;

        this.nameSet = false;

    }

    /**

     * Retrieves the user credentials and checks them. This is

     * the first part of the authentication process.

     */

    public boolean login() throws LoginException {

        // Retrieve the user credentials via the callback

        // handler.

        // In this case we get the user name from the HTTP

        // request parameters.

        Callback[] callbacks = new Callback[1];

        callbacks[0] = new HttpGetterCallback();

        /* The type and the name specify which part of the HTTP request

            * should be retrieved. For Web container authentication, the

            * supported types are defined in the interface

            * com.sap.engine.lib.security.http.HttpCallback.

            * For programmatical authentication with custom callback

            * handler the supported types depend on the used callback handler.

            */

        ((HttpGetterCallback) callbacks[0]).setType(

            HttpCallback.REQUEST_PARAMETER);

        //((HttpGetterCallback) callbacks[0]).setName("user_name");   

         ((HttpGetterCallback) callbacks[0]).setName("j_user");

        try {

            callbackHandler.handle(callbacks);

        } catch (UnsupportedCallbackException e) {

            return false;

        } catch (IOException e) {

            throwUserLoginException(e, LoginExceptionDetails.IO_EXCEPTION);

        }

        //Returns an array of all request parameters with name "user_name".

        String[] requestParameters =

            (String[]) ((HttpGetterCallback) callbacks[0]).getValue();

        if ((requestParameters != null) && requestParameters.length > 0) {

            userName = requestParameters[0];

        }

        if (userName == null) {

            throwNewLoginException("No user name provided.");

        }

                   

            /* When you know the user name, update the user information

                * using data from the persistence. The operation must

                * be done before the user credentials checks. This method also

                * checks the user name so that if a user with that name does not

                * exist in the active user store, a

                * java.lang.SecurityException is thrown.

                */

            try {

                refreshUserInfo(userName);

            } catch (SecurityException e) {

                throwUserLoginException(e);

            }

            /* Checks if the given user name starts with the specified

                * prefix in the login module options. If no prefix is specified,

                * then all users are trusted.

                */

            /*               

            String prefix = (String) options.get("user_name_prefix");

            if ((prefix != null) && !userName.startsWith(prefix)) {

                throwNewLoginException("The user is not trusted.");

            }

            */

            /* This is done if the authentication of the login module is    

                * successful.

                * Only one and exactly one login module from the stack must put

                * the user name in the shared state. This user name represents

                * the authenticated user.

                * For example if the login attempt is successful, method

                * getRemoteUser() of

                * the HTTP request will retrieve exactly this name.

                */

            if (sharedState.get(AbstractLoginModule.NAME) == null) {

                sharedState.put(AbstractLoginModule.NAME, userName);

                nameSet = true;

            }

           

       

            successful = true;

            return true;

       

    }

    /**

        * Commit the login. This is the second part of the authentication

        * process.

        * If a user name has been stored by the login() method,

        * the user name is added to the subject as a new principal.

        */

    public boolean commit() throws LoginException {

        if (successful) {

            /* The principals that are added to the subject should

             * implement java.security.Principal.You can use the class

             * com.sap.engine.lib.security.Principal for this purpose.

             */

            Principal principal = new Principal(userName);

            subject.getPrincipals().add(principal);

            /* If the login is successful, then the principal corresponding

             * to the <userName> (the same user name that has been added

             * to shared state) must be added in the shared state too.

             * This principal is considered to be the main principal

             * representing the user.

             * For example, this principal will be retrieved from method

             * getUserPrincipal() of the HTTP request.

             */

            if (nameSet) {

                sharedState.put(AbstractLoginModule.PRINCIPAL, principal);

            }

        } else {

            userName = null;

        }

        return true;

    }

    /**

     * Abort the authentication process.

     */

    public boolean abort() throws LoginException {

        if (successful) {

            userName = null;

            successful = false;

        }

        return true;

    }

    /**

     * Log out the user. Also removes the principals and

     * destroys or removes the credentials that were associated 

     * with the user during the commit phase.

     */

    public boolean logout() throws LoginException {

        // Remove principals and credentials from subject

        if (successful) {

            subject.getPrincipals(Principal.class).clear();

            successful = false;

        }

        return true;

    }

}

Accepted Solutions (1)

Accepted Solutions (1)

former_member301120
Active Participant
0 Kudos

Hello,

I solved the problem.

First you have to read the username with parameter "j_user".

After redeploying the library you have to remove the module once from the login modules stack.

After removing you can add it again. So the new (last deployed) code will be used.

Regards Christian

Answers (2)

Answers (2)

Former Member
0 Kudos

Hello,

I am facing the similar problem in Custom Login Module. I am trying to achieve Single Sign On for our Application. I am using NWDS 7.0.

The statement,

String[] requestParameters = (String[]) ((HttpGetterCallback) callbacks[0]).getValue();

is returning null. Used debuggers to get the value of requestParameters.

The callback is happening correctly. But not getting the value against name 'user_name' which I am trying to fetch from the url of our Application.

As suggested by Christian, I removed the Login module from Login Module Stack and added it again.

But It didn't work.

Kindly suggest a solution to resolve the issue.

DK007
Active Participant
0 Kudos

Hello Christian,

You have to use NameCallback to read user name and PasswordCallback to read password in custom login module.

Attached is the BasicPasswordLoginModule code of NW 7.3 version. I used same code that is provided in standard and could able to read user name and password in my custom login module.

For NW 7.0 version you need to decompile the code.

Thanks,

Dheeram

DK007
Active Participant
0 Kudos

Try using number 3 instead HttpCallback.REQUEST_PARAMETER for setting setType on a call back object at line 73 and 74 in your code. I had similar issue.

Code: ((HttpGetterCallback)callbacks[0].setType(3);

former_member301120
Active Participant
0 Kudos

Hello,

thanks for the hint. Where can I get the  BasicPasswordLoginModule from SAP Netwweaver 7.0

Regards Christian

former_member301120
Active Participant
0 Kudos

I found it.

It's in the securtity.jar file.

Former Member
0 Kudos

Hi there,

Where did you get the source code from? I cant find classes SecurityContextImpl and BaseLoginException and I think they are in the same jar, I dont need the code, just the libraries. Does anyone know where they are?

former_member301120
Active Participant
0 Kudos

Hello Daniel,

you need the file security_api.jar.

Regards Christian

Former Member
0 Kudos

Thanks Christian, do you know where can I find it?

0 Kudos

Hi Dheeram,

  I am doing portal login error message customization for one of our customer.

The customer use case is to display "Invalid password" if the user gives wrong password

instead of the default error message "User authentication failed".

I had gone through lot of SCN blogs and I finally came to a conclusion that the steps provided in the below help link is

the proper procedure (Creating a custom logon module) for doing the customization.

http://help.sap.com/saphelp_nw70/helpdata/en/46/3ce9402f3f8031e10000000a1550b0/content.htm?frameset=...

After which I had a chance to go through this discussion which I felt gave me some more clarity for the issue.

But still I am not very clear in few things.

Below are my questions for which I need clarifications:

1) Can we follow the same procedure as said in the above link for EP 7.0 as well ?

2) Whether the attachment provided( BasicPasswordLoginModule-NW7.3.txt.zip )  is the custom logon module created by you ?

3) From which location I can access the BasicPasswordLoginModule file from the server?

Many thanks in advance for your help.

Regards,

Parthibaraja