Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

Basic Auth

Basic Auth refers to the classic authentication method, where in order to authenticate with your API users simply provide the Anypoint™ Connector their username and password. This is also the scheme you want to use if your API relies on Basic Auth, using atypical values for the username and password. For instance, an API that uses a security token on top of the username and password would still use Basic Auth for its connecting applications.

The Anypoint DevKit Basic Auth framework provides multi-tenancy capabilities for a connector (managing multiple simultaneous connections with different credentials for a given connector within your application), as well as connection pooling and instance pooling. These benefits are available for most authentication schemes other than OAuth, and for APIs that do not require authentication.

This document describes the benefits of using the Basic Auth framework, the Java annotations through which it is exposed, and how to implement Basic Auth support in your own connector to authenticate with your API. Examples in this discussion show the use of Basic Authentication with basic username/password authentication, but they can easily be generalized to other non-OAuth protocols.

5-package

Assumptions

This document assumes you are familiar with the Anypoint Connector DevKit, have already created a connector project, and are ready to implement authentication on your connector. Further, it assumes you are familiar with the various authentication methods, have compared the different authentication support options in Devkit, and chosen Basic Authentication to connect to your API.

About Basic Authentication

Anypoint DevKit’s Basic Auth framework provides the following benefits with minimal effort on the part of the connector developer:

  • Transparent multitenancy – a Mule application can open many connections to a single target, using different credentials to connect on behalf of many users simultaneously

  • Connection pooling – automated management of a pool of instances of the connector class, to manage connection resources effectively

  • The ability to automatically invalidate connections on exceptions, and to reconnect as needed

Anypoint DevKit makes it easy to add Basic Authentication functionality to connectors by applying annotations at the @Connector class level.

Connection Management Framework and Authentication Protocols

The Basic Auth framework can be used in conjunction with most authentication protocols, such as basic username/password authentication (most common), SAML, Kerberos, LDAP and NTLM.

However, you cannot use the Basic Authentication framework with connectors that use OAuth authentication; the framework does not support the "OAuth dance" or the management of OAuth tokens.

OAuth-based authentication in DevKit provides functionality comparable to the Basic Authentication, if you use the OAuth-related annotations. See OAuth V1 and OAuth V2 for details.

Basic Auth Annotations in DevKit

To use Basic Authentication in a connector, define and annotate the following methods in the @Connector class:

  • @Connect method - Creates a connection

  • @Disconnect method - Explicitly closes a connection

  • @ValidateConnection method - Returns true if a connection is still valid, false otherwise

  • @ConnectionIdentifier method - Returns a prefix used in generating unique identifies for connector instances in the connection pool

Also available is an @InvalidateConnectionOn method for when an API operation encounters an exception due to a lost connection.

The specific implementation of these methods depends on the target.

Because Basic Authentication is such a useful and fundamental feature, the generated code skeleton includes placeholder methods with the Basic Authentication annotations already applied:

Skeleton Connector with Connection Management Annotated Methods

              
           
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/**
* Connect
*
* @param username A username
* @param password A password
* @throws ConnectionException
*/
@Connect public void connect(@ConnectionKey String username, String password)
    throws ConnectionException
{
 
    /**
    * CODE FOR ESTABLISHING A CONNECTION GOES HERE 
    */
}
 
/**
* Disconnect
*/ 
@Disconnect
public void disconnect()
{
 
    /**
    * CODE FOR CLOSING A CONNECTION GOES HERE
    */
}
 
/**
* Validate Connection
*/
@ValidateConnection
public boolean isConnected()
{
    //CHECK IF THE CONNECTION IS OPEN
}
 
/**
* Connection identifier
*/
@ConnectionIdentifier
public String connectionId()
{
    return "001";
}
When developing your connector, make sure to incorporate connection logic that pertains to your connector.

The methods are called automatically as needed by the Anypoint DevKit framework; you never call them directly from your code.

@Connect Method

This method designates which method inside an @Connector class is responsible for creating a connection to the target. The @Connect method is called automatically by Mule when the connector starts up, or if the connection to the API has been lost and must be reestablished. When this method finishes, if authentication is successful, the connector instance is ready to make requests to the API.

A method annotated with @Connect must:

  • Be public

  • Throw org.mule.api.ConnectionException (and no other exceptions)

  • Have a void return type

  • If automatic Basic Authentication is used, have exactly one method annotated @Connect; otherwise compilation fails

The specific code that implements the actual connection depends on the API. Here is an example implementation of a @Connect method:

Connect method for salesforce connector

              
           
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Connect
public void connect(@ConnectionKey String username, String password)
throws ConnectionException
{
   ConnectorConfig config = new ConnectorConfig();
   config.setUsername(username);
   config.setPassword(password);
   try
   {
      connection = com.mycompany.ws.Connector.newConnection(config);
   }
   catch (com.mycompany.ws.ConnectionException e)
   {
      throw new org.mule.api.ConnectionException(ConnectionExceptionCode.UNKNOWN, null, e.getMessage(), e);
   }
}

The parameters required by this method are the credentials needed for authentication, in this case username and password. Since this method is annotated with @Connect, Anypoint DevKit makes these parameters available both in the configuration element for this connector (as occurs with @Configurable fields), as well as in the message processor whenever it is dragged into a flow. Specified credentials override those that are set in the configuration element.

@ConnectionKey and Connection Pooling

The username parameter is annotated with @ConnectionKey. If pools are enabled (see Connection Pooling below), Mule keeps a pool of simultaneous connections which are used as needed to make calls. The @ConnectionKey annotation marks that this field is used as the key for this particular connection within the connection pool, so once a connection for this username has been created and added to the pool, it will be reused rather than recreated for each request.


Choosing a Connection Key

For username and password authentication, the username is the obvious choice for @ConnectionKey. For other protocols, identify the value that is most obviously associated with different users and access privileges that connect to your service, and use this value as your @ConnectionKey. ====


In the example above, the @Connect method first creates a ConnectorConfig object (a Salesforce type that holds connection configuration information), then loads the username and password values into the object. This object is used as the argument to the static newConnection() call, which returns a PartnerConnection if successful. If the authentication fails (for example because of invalid login information) the code catches the Salesforce typed exception and throws a new exception containing the same information but labeled as the correct Mule exception type.

Note the use of the fully qualified name for the Salesforce Connector class (on which you call newConnection(config)) rather than importing the class. This is because DevKit also imports a class called Connector, which causes an import conflict.
For clients where no authentication is used, you must still supply a @ConnectionKey field. An invented username is one possibility; see Creating a Connector for a SOAP Service Via CXF Client for such an implementation.

== @Disconnect Method

This annotation indicates the method inside a @Connector class that is responsible for disposal of a connection. This method is called when the connector is shut down or the connection is explicitly terminated.

A method annotated with @Disconnect must:

  • Be public

  • Take no input parameters

  • Have a void return type

If Basic Authentication is used, the @Connector class must have exactly one annotated @Disconnect method; otherwise compilation fails.


              
           
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Disconnect
public void disconnect()
{
   if (connection != null)
   {
       try
         {
         connection.logout();
         }
      catch (ConnectionException e)
         {
         e.printStackTrace();
         }
      finally
         {
         connection = null;
         }
   }
}

If the connector currently has a connection open, this code calls connection.logout(), a client method that explicitly de-authenticates and closes the connection. The finally block ensures that, if the logout fails for any reason, the connection is still set to null, so the connector does not again try to reference that connector instance.

== @ValidateConnection Method

This method is called by Mule to check whether the connection is actually open or not.

A method annotated with @ValidateConnection must:

  • Be public

  • Take no input parameters

  • Return boolean or java.lang.Boolean

Only one method on a @Connector class can be annotated with @ValidateConnection.


              
           
1
2
3
4
5
@ValidateConnection    
public boolean isConnected() 
{     
return connection != null;    
}

In this example, in order to determine whether the connection is active the code simply checks if the connection parameter is null. A different implementation may be required for other connectors, depending on the protocol.

== @ConnectionIdentifier Method

This annotation identifies a method inside a @Connector class that returns a unique identifier for the connection, used for logging and debugging.

A method annotated with @ConnectionIdentifier must:

  • Be public

  • Not be static

  • Not take arguments

  • Return java.lang.String

A @Connector class that uses Basic Authentication must have exactly one method annotated @ConnectionIdentifier; otherwise compilation will fail.

This code returns the connection SessionId as an identifier (if available). The SessionHeader object in this case contains header information about the current connection to the API, including the session ID.


              
           
1
2
3
4
5
6
7
8
@ConnectionIdentifier
   public String connectionId() {
    if (connection != null){
     return connection.getSessionHeader().getSessionId();
    } else {
     return null;
    }
   } 

== @ReconnectOn Annotation

This annotation deprecates @InvalidateConnectionOn annotation. It now receives a list of exceptions instead of just a single exception, and can be used at both the class and processor levels.

This annotation is used for exception handling related to connections. It can be used at a class level (annotated with the @Connector annotation) or at a method level (annotated with @Processor annotation). If the Connector or Processor throws an exception of this class, @ReconnectOn automatically invalidates the connection. @ReconnectOn receives a list containing the classes of the exceptions to be caught (see below for an example). When an exception occurs, `@ReconnectOn’s behavior is based on the configured reconnection strategy. See Configuring Reconnection Strategies for more details.


              
           
1
2
3
4
5
6
7
8
9
@Processor
@ReconnectOn(exceptions = {InvalidSessionFault.class, PasswordChangedException.class})
public void myOperation(@Optional String source,
                        @Optional Object destination) throws InvalidSessionFault, PasswordChangedException, InvalidParameterException
{
    /**
    * CODE FOR MY OPERATION
    */
}

== Connection Pooling

You can allow users of your connector to use a pool of simultaneous connections instead of sharing a single instance to process messages.

Connectors that implement pools are each assigned a pool component, which contains multiple instances of the connector to handle simultaneous requests. A connector’s configuration pooling profile configures its component pool.

If you set the poolable annotation parameter to true, the generated schema will include additional configuration elements.

=== Example

Connector

                   
                
1
2
3
4
5
6
7
@Connector(name = "myconnector", poolable = true)
public class MyConnector
{
    /**
    * CODE
    */
}

In the corresponding XML, the pooling-config element is nested inside the config element. Notice that there is no need to provide any custom Java code to handle the pool, all that is needed is to provide a few parameters:

XML

                   
                
1
2
3
4
5
<mymodule:config>
    <mymodule:pooling-profile maxActive="10" maxIdle="5"
        initialisationPolicy="INITIALISE_ALL"
        exhaustedAction="WHEN_EXHAUSTED_FAIL" maxWait="60"/>
</mymodule:config>

The following table lists pooling-profile parameters:

Attribute Description

maxActive

Required. Controls the maximum number of Mule components that can be borrowed from a session at once. A negative value means no limit. When maxActive is exceeded, the pool is said to be exhausted.

maxIdle

Required. Controls the maximum number of Mule components that can sit idle in the pool at once. A negative value means no limit.

initialisationPolicy

Optional. Determines how components in a pool should be initialized. Possible values:

  • INITIALISE_NONE (does not load any components into the pool on startup)

  • INITIALISE_ONE (loads one initial component into the pool on startup)

  • INITIALISE_ALL (loads all components in the pool on startup).

The default value is INITIALISE_ONE.

exhaustedAction

Optional. Specifies the behavior of the Mule component pool when the pool is exhausted. Its possible values are:

  • WHEN_EXHAUSTED_FAIL (throw a NoSuchElementException)

  • WHEN_EXHAUSTED_WAIT (block by invoking Object.wait(long) until a new or idle object is available)

  • WHEN_EXHAUSTED_GROW (create a new Mule instance and return it, invalidating maxActive).

If a positive maxWait value is supplied, it blocks for at most that many milliseconds, after which a NoSuchElementException is thrown. If maxWait is a negative value, it blocks indefinitely.

The default value is WHEN_EXHAUSTED_GROW.

maxWait

Required. Specifies the number of milliseconds to wait for a pooled component to become available when the pool is exhausted and the exhaustedAction is set to WHEN_EXHAUSTED_WAIT.

== See Also