WSO2 Identity Server Dropbox Authenticator


Each authenticator provides you a way to authenticate the user using specific external authentication system. For example if you want to authenticate a user who logs into your application using Dropbox authenticator, you need to configure the Dropbox authenticator for your identity provider .The Dropbox authenticator allows you to authenticate user using Dropbox through WSO2 IS. 


Before you can get started, you'll need to register your app with Dropbox by creating a new app in My apps. That page will guide you through the process of registering your app, including choosing which permission your app needs, and specifying an app name. After creating your app, you're ready to set up the authorization process in your app. The Dropbox SDKs will take care of some of the OAuth 2 process automatically for you, and you can use the tutorials and sample apps for reference.

Configuring the Dropbox App

Step 1. go to https://www.dropbox.com/developers/apps and create new app as described  in the Doc.

Step 2.Enter the name of your new app and redirect URL https://localhost:9443/commonauth in the window that appears.

Step 3.  Copy App key and App Secret from above page

Deploying travelocity.com sample app

The next step is to deploy the sample app in order to use it in this scenario.
  1. You can download travelocity.com.war file from here.
  2. Deploy this sample web app on a web container.
    1. Use the Apache Tomcat server to do this.
    2. Since this sample is written based on Servlet 3.0, it needs to be deployed on Tomcat 7.x.
    3. Copy the .war file into the webapps folder. For example, <APACHE_HOME>/apache-tomcat-7.0.50/webapps.
Once this is done, the next step is to configure the WSO2 Identity Server by adding a service provider and identity provider.

Now you have to configure WSO2 Identity Server by adding a new identity provider.
  1. Download the WSO2 Identity Server from here and run it.
  2. Log in to the management console as an administrator.
  3. In the Identity Providers section under the Main tab of the management console, click Add.
  4. Give a suitable name for Identity Provider Name.

  1. Go to Dropbox Configuration under Federated Authenticators.
  2. Enter the values as given in the above figure.
    • Client Id: App key for your app.
    • Client Secret: App Secret for your app.
    • Callback URL: Service Provider's URL where code needs to be sent .
  3. Select both checkboxes to Enable the Foursquare Authenticator and make it the Default.
  4. Click Register.
You have now added the identity provider.


Configuring the service provider

The next step is to configure the service provider.
  1. Return to the management console.
  2. In the Service Providers section under the Main tab, click Add.
  3. Since you are using travelocity as the sample, enter travelocity.com in the Service Provider Name text box and click Register.
  4. In the Inbound Authentication Configuration section, click Configure under the SAML2 Web SSO Configuration section.

  5. Now set the configuration as follows:
    1. Issuer: travelocity.com
    2. Assertion Consumer URL: http://localhost:8080/travelocity.com/home.jsp
  6. Select the following check-boxes:
    1. Enable Response Signing.
    2. Enable Single Logout.
    3. Enable Attribute Profile.
    4. Include Attributes in the Response Always.
  7. Click Update to save the changes. Now you will be sent back to the Service Providers page.
  8. Go to the Local and Outbound Authentication Configuration section.
  9. Select the identity provider you created from the dropdown list under Federated Authentication.

  10. Ensure that the Federated Authentication radio button is selected and click Update to save the changes.

 You have now added and configured the service provider.


Testing the sample

  1. To test the sample, go to the following URL: http://<TOMCAT_HOST>:<TOMCAT_PORT>/travelocity.com/index.jsp E.g., http://localhost:8080/travelocity.com
  2. Click the link to log in with SAML from WSO2 Identity Server.
You are redirected to the Foursquare Login page. Enter your Dropbox credentials and you will be taken to the home page of the travelocity.com app.
After Successfully Login you will get a page with claims. Dropbox will provide below information for claims


fielddescription
uidThe user's unique Dropbox ID.
display_nameThe user's display name.
name_details/given_nameThe user's given name.
name_details/surnameThe user's surname.
name_details/familiar_nameThe locale-dependent familiar name for the user.
referral_linkThe user's referral link.
countryThe user's two-letter country code, if available.
localeLocale preference set by the user (e.g. en-us).
emailThe user's email address.
email_verifiedIf true, the user's email address has been verified to belong to that user.
is_pairedIf true, there is a paired account associated with this user.
teamIf the user belongs to a team, contains team information. Otherwise, null.
team/nameThe name of the team the user belongs to.
team/team_idThe ID of the team the user belongs to.
quota_info/normalThe user's used quota outside of shared folders (bytes).
quota_info/sharedThe user's used quota in shared folders (bytes). If the user belongs to a team, this includes all usage contributed to the team's quota outside of the user's own used quota (bytes).
quota_info/quotaThe user's total quota allocation (bytes). If the user belongs to a team, the team's total quota allocation (bytes).



Creating WSO2 IS Custom Federated Authenticator

WSO2 IS custom authenticators provides you a way to authenticate the user using specific external authentication system. through the authenticators we can secure our systems. Before start development Research the APIs provided by the service for which you want to create an authenticator.






  1. Create a folder name called Sample
  2. within folder generate archetype. then you will get the archetype like in image
mvn archetype:generate -DarchetypeGroupId=org.wso2.carbon.extension.archetype -DarchetypeArtifactId=org.wso2.carbon.extension.archetype.is.authenticator-archetype -DarchetypeVersion=1.0.1 -DgroupId=org.wso2.carbon.extension.identity.authenticator -DartifactId=org.wso2.carbon.extension.identity.authenticator.sample -Dversion=1.0.0 -DarchetypeRepository=http://maven.wso2.org/nexus/content/repositories/wso2-public/





The following code block represents the structure of an authenticator pom.xml. Authenticators are basically OSGi (Open Service Gateway initiative) bundles, which are units of modularization that are comprised of Java classes and other resources that provide functions to end users. The pom.xml includes the dependencies for the project.


<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2016 WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.extension.identity.authenticator</groupId>
<artifactId>org.wso2.carbon.extension.identity.authenticator.sample</artifactId>
<version>1.0.0</version>

<packaging>bundle</packaging>
<name>WSO2 Carbon - Authenticator Library For Sample</name>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.idp.mgt</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
<version>${commons-logging.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.application.common</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.user.profile</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.user.account.association</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.core</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.application.authentication.framework</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.notification.mgt</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.provisioning</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.core</artifactId>
<version>${carbon.kernel.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.core</artifactId>
<version>${carbon.kernel.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.application.mgt</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.client</artifactId>
<version>0.31</version>
</dependency>
<dependency>
<groupId>org.apache.oltu.oauth2</groupId>
<artifactId>org.apache.oltu.oauth2.common</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.application.authenticator.openid</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon.identity</groupId>
<artifactId>org.wso2.carbon.identity.application.authenticator.oidc</artifactId>
<version>${carbon.identity.version}</version>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.ui</artifactId>
<version>${carbon.kernel.version}</version>
</dependency>
<dependency>
<groupId>org.json.wso2</groupId>
<artifactId>json</artifactId>
<version>${wso2.json}</version>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.5</version>
<extensions>true</extensions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>org.wso2.carbon.extension.identity.authenticator.internal</Private-Package>
<Import-Package>
org.apache.commons.logging.*; version="1.0.4",
org.osgi.framework,
org.wso2.carbon.identity.application.authentication.framework.*,
javax.servlet,
javax.servlet.http,
org.apache.oltu.oauth2.*; version="${oltu.package.import.version.range}",
*;resolution:=optional
</Import-Package>
<Export-Package>
!org.wso2.carbon.extension.identity.authenticator.internal,
org.wso2.carbon.identity.authenticator.*
</Export-Package>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<carbon.identity.version>5.0.7</carbon.identity.version>
<commons-logging.version>4.4.3</commons-logging.version>
<carbon.kernel.version>4.4.3</carbon.kernel.version>
<oltu.version>1.0.0.wso2v2</oltu.version>
<org.apache.oltu.oauth2.client.version>1.0.0</org.apache.oltu.oauth2.client.version>
<oltu.package.import.version.range>[1.0.0, 2.0.0)</oltu.package.import.version.range>
<wso2.json>3.0.0.wso2v1</wso2.json>
</properties>
</project>

Since the project is an OSGi bundle, you must add this class to define the bundle activate method and deactivate method.

/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

package org.wso2.carbon.extension.identity.authenticator.internal;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.identity.application.authentication.framework.ApplicationAuthenticator;
import org.wso2.carbon.extension.identity.authenticator.SampleAuthenticator;

import java.util.Hashtable;

/**
* @scr.component name="identity.application.authenticator.Sample.component" immediate="true"
*/
public class SampleAuthenticatorServiceComponent {

private static Log log = LogFactory.getLog(SampleAuthenticatorServiceComponent.class);

/**
*
*/
protected void activate(ComponentContext ctxt) {
try {
SampleAuthenticator authenticator = new SampleAuthenticator();
Hashtable<String, String> props = new Hashtable<String, String>();
ctxt.getBundleContext().registerService(ApplicationAuthenticator.class.getName(),
authenticator, props);
if (log.isDebugEnabled()) {
log.debug("Sample authenticator is activated");
}
} catch (Throwable e) {
log.fatal("Error while activating the Sample authenticator ", e);
}
}
/**
*
*/
protected void deactivate(ComponentContext ctxt) {
if (log.isDebugEnabled()) {
log.debug("Sample authenticator is deactivated");
}
}
}

/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

package org.wso2.carbon.extension.identity.authenticator;

public class SampleAuthenticatorConstants {
public static final String AUTHENTICATOR_NAME = "Sample";
public static final String AUTHENTICATOR_FRIENDLY_NAME = "SampleAuthenticator";
//Sample authorize endpoint URL
public static final String Sample_OAUTH_ENDPOINT = "";
//Sample token endpoint URL
public static final String Sample_TOKEN_ENDPOINT = "";
//Sample user info endpoint URL
public static final String Sample_USERINFO_ENDPOINT = "";
}

After adding this to your project, you are in a position to write your authenticator. Authenticators are defined by extending the AbstractApplicationAuthenticator class and implementing the FederatedApplicationAuthenticator interface. The important methods in the AbstractApplicationAuthenticator class and the FederatedApplicationAuthenticator interface are listed as follows.
  • public String getName()
  • public String getFriendlyName()
  • public String getContextIdentifier(HttpServletRequest request) - Returns a unique identifier that will map the authentication request and the response. The value returned by the invocation of authentication request and the response should be the same.
  • public boolean canHandle(HttpServletRequest request) - Specifies whether this authenticator can handle the authentication response.
  • protected void initiateAuthenticationRequest(HttpServletRequest request,HttpServletResponse response, AuthenticationContext context)
  • protected void processAuthenticationResponse(HttpServletRequest request,HttpServletResponse response, AuthenticationContext context)

/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/

package org.wso2.carbon.extension.identity.authenticator;

import org.apache.oltu.oauth2.client.response.OAuthClientResponse;
import org.wso2.carbon.identity.application.authenticator.oidc.OpenIDConnectAuthenticator;
import org.wso2.carbon.identity.application.authentication.framework.FederatedApplicationAuthenticator;
import org.wso2.carbon.identity.application.common.model.Property;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
* Authenticator of Sample
*/
public class SampleAuthenticator extends OpenIDConnectAuthenticator
implements FederatedApplicationAuthenticator {

private static Log log = LogFactory.getLog(SampleAuthenticator.class);

/**
* Get Sample authorization endpoint.
*/
@Override
protected String getAuthorizationServerEndpoint(Map< String, String > authenticatorProperties) {
return SampleAuthenticatorConstants.Sample_OAUTH_ENDPOINT;
}

/**
* Get Sample token endpoint.
*/
@Override
protected String getTokenEndpoint(Map< String, String > authenticatorProperties) {
return SampleAuthenticatorConstants.Sample_TOKEN_ENDPOINT;
}

/**
* Get Sample user info endpoint.
*/
@Override
protected String getUserInfoEndpoint(OAuthClientResponse token, Map< String, String > authenticatorProperties) {
return SampleAuthenticatorConstants.Sample_USERINFO_ENDPOINT;
}

/**
* Check ID token in Sample OAuth.
*/
@Override
protected boolean requiredIDToken(Map< String, String > authenticatorProperties) {
return false;
}

/**
* Get the friendly name of the Authenticator
*/
@Override
public String getFriendlyName() {
return SampleAuthenticatorConstants.AUTHENTICATOR_FRIENDLY_NAME;
}

/**
* Get the name of the Authenticator
*/
@Override
public String getName() {
return SampleAuthenticatorConstants.AUTHENTICATOR_NAME;
}

/**
* Get Configuration Properties
*/
@Override
public List<Property> getConfigurationProperties() {

List<Property> configProperties = new ArrayList<Property>();
//Add your configuration properties
return configProperties;
}
}

  1. Implement the canHandle() method using the above methods. When API sends the OAuth response, it sends the parameters oauth_token and oauth_verifier in the request. This is a notification to identify that this response can be handled by the authenticator.
  2. For each authentication request that comes into the Identity Server, there is unique value that comes along as a parameter. That parameter is the sessionDataKey. Store this in the API authentication redirection session to facilitate the requirement where getContextIdentifier gives the same value for authentication request and its response.
  3. Next, implement the initiateAuthenticationRequest method and the processAuthenticationResponse method.
  4. The buildClaims method saves the retrieved user attributes to the authenticated context in the Identity Server. That is needed to map the claims to the built in claims of IS.
  5. After implementing these methods you can build your bundle. After building it you have to put that into the <IS_HOME>/repository/components/dropins directory.
  6. Restart the Identity Server and configure the authenticators for your identity provider to reach out to third party authentication