keycloak-aplcache

KEYCLOAK-2348 - Social login provider for Microsoft Live account

1/19/2016 1:40:38 PM

Changes

pom.xml 5(+5 -0)

social/pom.xml 1(+1 -0)

Details

diff --git a/dependencies/server-all/pom.xml b/dependencies/server-all/pom.xml
index b7d901c..7d0bac0 100755
--- a/dependencies/server-all/pom.xml
+++ b/dependencies/server-all/pom.xml
@@ -94,6 +94,10 @@
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-social-stackoverflow</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-microsoft</artifactId>
+        </dependency>
 
         <!-- ldap federation api -->
         <dependency>
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml
index 0a67753..914bd72 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml
@@ -43,6 +43,7 @@
             <module name="org.keycloak.keycloak-social-twitter" services="import"/>
             <module name="org.keycloak.keycloak-social-linkedin" services="import"/>
             <module name="org.keycloak.keycloak-social-stackoverflow" services="import"/>
+            <module name="org.keycloak.keycloak-social-microsoft" services="import"/>
             <module name="org.keycloak.keycloak-timer-api" services="import"/>
             <module name="org.keycloak.keycloak-timer-basic" services="import"/>
             <module name="org.hibernate" services="import"/>
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-services/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-services/main/module.xml
index 12d9ebb..eda4bf4 100755
--- a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-services/main/module.xml
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-services/main/module.xml
@@ -54,6 +54,7 @@
         <module name="org.keycloak.keycloak-social-twitter" services="import"/>
         <module name="org.keycloak.keycloak-social-linkedin" services="import"/>
         <module name="org.keycloak.keycloak-social-stackoverflow" services="import"/>
+        <module name="org.keycloak.keycloak-social-microsoft" services="import"/>
         <module name="org.keycloak.keycloak-timer-api" services="import"/>
         <module name="org.keycloak.keycloak-timer-basic" services="import"/>
         <module name="org.keycloak.keycloak-wildfly-extensions" services="import"/>
diff --git a/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-social-microsoft/main/module.xml b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-social-microsoft/main/module.xml
new file mode 100755
index 0000000..1b22ce8
--- /dev/null
+++ b/distribution/feature-packs/server-feature-pack/src/main/resources/modules/system/layers/base/org/keycloak/keycloak-social-microsoft/main/module.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-social-microsoft">
+    <resources>
+        <artifact name="${org.keycloak:keycloak-social-microsoft}"/>
+    </resources>
+    <dependencies>
+        <module name="org.keycloak.keycloak-common"/>
+        <module name="org.keycloak.keycloak-core"/>
+        <module name="org.keycloak.keycloak-social-core"/>
+        <module name="org.keycloak.keycloak-broker-core"/>
+        <module name="org.keycloak.keycloak-broker-oidc"/>
+        <module name="org.keycloak.keycloak-model-api"/>
+        <module name="org.jboss.logging"/>
+        <module name="javax.api"/>
+        <module name="org.codehaus.jackson.jackson-core-asl"/>
+        <module name="org.codehaus.jackson.jackson-mapper-asl"/>
+        <module name="org.codehaus.jackson.jackson-xc"/>
+    </dependencies>
+
+</module>
diff --git a/distribution/server-overlay/eap6/eap6-server-modules/build.xml b/distribution/server-overlay/eap6/eap6-server-modules/build.xml
index 97cbb6f..51e7280 100755
--- a/distribution/server-overlay/eap6/eap6-server-modules/build.xml
+++ b/distribution/server-overlay/eap6/eap6-server-modules/build.xml
@@ -236,6 +236,10 @@
       	<module-def name="org.keycloak.keycloak-social-stackoverflow">
     	      <maven-resource group="org.keycloak" artifact="keycloak-social-stackoverflow"/>
     	  </module-def>
+    	
+    	  <module-def name="org.keycloak.keycloak-social-microsoft">
+    	    	      <maven-resource group="org.keycloak" artifact="keycloak-social-microsoft"/>
+    	  </module-def>
 
         <module-def name="org.keycloak.keycloak-kerberos-federation">
             <maven-resource group="org.keycloak" artifact="keycloak-kerberos-federation"/>
diff --git a/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-eap6-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml b/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-eap6-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml
index 0a67753..914bd72 100755
--- a/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-eap6-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml
+++ b/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-eap6-server-subsystem/main/server-war/WEB-INF/jboss-deployment-structure.xml
@@ -43,6 +43,7 @@
             <module name="org.keycloak.keycloak-social-twitter" services="import"/>
             <module name="org.keycloak.keycloak-social-linkedin" services="import"/>
             <module name="org.keycloak.keycloak-social-stackoverflow" services="import"/>
+            <module name="org.keycloak.keycloak-social-microsoft" services="import"/>
             <module name="org.keycloak.keycloak-timer-api" services="import"/>
             <module name="org.keycloak.keycloak-timer-basic" services="import"/>
             <module name="org.hibernate" services="import"/>
diff --git a/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml b/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
index 893c5e2..9f6204c 100755
--- a/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
+++ b/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-services/main/module.xml
@@ -55,6 +55,7 @@
         <module name="org.keycloak.keycloak-social-twitter" services="import"/>
         <module name="org.keycloak.keycloak-social-linkedin" services="import"/>
         <module name="org.keycloak.keycloak-social-stackoverflow" services="import"/>
+        <module name="org.keycloak.keycloak-social-microsoft" services="import"/>
         <module name="org.keycloak.keycloak-timer-api" services="import"/>
         <module name="org.keycloak.keycloak-timer-basic" services="import"/>
         <module name="org.keycloak.keycloak-wildfly-extensions" services="import"/>
diff --git a/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-social-microsoft/main/module.xml b/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-social-microsoft/main/module.xml
new file mode 100755
index 0000000..2d75d15
--- /dev/null
+++ b/distribution/server-overlay/eap6/eap6-server-modules/src/main/resources/modules/org/keycloak/keycloak-social-microsoft/main/module.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+
+
+<module xmlns="urn:jboss:module:1.1" name="org.keycloak.keycloak-social-microsoft">
+    <resources>
+        <!-- Insert resources here -->
+    </resources>
+    <dependencies>
+        <module name="org.keycloak.keycloak-common"/>
+        <module name="org.keycloak.keycloak-core"/>
+        <module name="org.keycloak.keycloak-social-core"/>
+        <module name="org.keycloak.keycloak-broker-core"/>
+        <module name="org.keycloak.keycloak-broker-oidc"/>
+        <module name="org.keycloak.keycloak-model-api"/>
+        <module name="org.jboss.logging"/>
+        <module name="javax.api"/>
+        <module name="org.codehaus.jackson.jackson-core-asl"/>
+        <module name="org.codehaus.jackson.jackson-mapper-asl"/>
+        <module name="org.codehaus.jackson.jackson-xc"/>
+    </dependencies>
+
+</module>
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/identity-broker.xml b/docbook/auth-server-docs/reference/en/en-US/modules/identity-broker.xml
index c0183ba..8e32dec 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/identity-broker.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/identity-broker.xml
@@ -211,7 +211,7 @@
                     <para>
                         Social providers allows you to enable social authentication to your realm.
                         Keycloak makes it easy to let users log in to your application using an existing account with a social network.
-                        Currently Facebook, Google, Twitter, GitHub, LinkedIn and StackOverflow are supported with more planned for the future.
+                        Currently Facebook, Google, Twitter, GitHub, LinkedIn, Microsoft and StackOverflow are supported with more planned for the future.
                     </para>
                 </listitem>
             </varlistentry>
@@ -357,7 +357,7 @@
             So is trying to remember yet another username and password combination.
             Social identity providers makes it easy for users to register on your realm and quickly sign in using a social network.
             Keycloak provides built-in support for the most common social networks out there, such as Google, Facebook, Twitter,
-            Github, LinkedId and StackOverflow.
+            Github, LinkedId, Microsoft and StackOverflow.
         </para>
 
         <section>
@@ -856,6 +856,95 @@
             </table>
         </section>
         <section>
+            <title>Microsoft</title>
+            <para>
+                To enable login with Microsoft account you first have to register an OAuth application on
+                <ulink url="https://account.live.com/developers/applications/index">Microsoft account Developer Center</ulink>. Then you need to copy the client id and secret into the Keycloak Admin Console.
+            </para>
+            <para>
+                Let's see first how to create an application with Microsoft.
+            </para>
+            <orderedlist>
+                <listitem>
+                    <para>
+                        Go to <ulink url="https://account.live.com/developers/applications/create">create new application on Microsoft account Developer Center</ulink> url and login here. 
+                        Use any value for <literal>Application Name</literal>, <literal>Application Logo</literal> and <literal>URLs</literal> you want.
+                        In <literal>API Settings</literal> set <literal>Target Domain</literal> to the domain where your Keycloak instance runs.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        Copy <literal>Client Id</literal> and <literal>Client Secret</literal> from <literal>App Settings</literal> page.
+                    </para>
+                </listitem>
+            </orderedlist>
+            <para>
+                Now that you have the client id and secret you can proceed with the creation of a Microsoft Identity Provider in Keycloak. As follows:
+            </para>
+            <orderedlist>
+                <listitem>
+                    <para>
+                        Select the <literal>Microsoft</literal> identity provider from the drop-down box on the top right corner of the identity providers table in Keycloak's Admin Console. You should be presented with a specific page to configure the selected provided.
+                    </para>
+                </listitem>
+                <listitem>
+                    <para>
+                        Copy the client id and client secret to their corresponding fields in the Keycloak Admin Console. Click <literal>Save</literal>.
+                    </para>
+                </listitem>
+            </orderedlist>
+            <para>
+                Once you create the identity provider in Keycloak, you must update your Microsoft application with the redirect url that was
+                generated to your identity provider.
+            </para>
+            <orderedlist>
+                <listitem>
+                    <para>
+                        Open the Microsoft account Developer Center and select <literal>API Settings</literal> of your application. In <literal>Redirect URLs</literal>
+                        insert the redirect uri created by Keycloak. The redirect uri
+                        usually have the following format: <literal>http://{host}:{port}/auth/realms/{realm}/broker/microsoft/endpoint</literal>.
+                    </para>
+                </listitem>
+            </orderedlist>
+            <note>
+                <para>
+                    You can always get the redirect url for a specific identity provider from the table presented when you
+                    click on the 'Identity Provider' tab in <emphasis>Realm > Settings</emphasis>.
+                </para>
+            </note>
+            <para>
+                That is it! This pretty much what you need to do in order to setup this identity provider.
+            </para>
+             <para>
+                The table below lists some additional configuration options you may use when configuring this provider.
+            </para>
+            <table>
+                <title>Configuration Options</title>
+                <tgroup align="left" cols="2">
+                    <thead>
+                        <row>
+                            <entry>
+                                Configuration
+                            </entry>
+                            <entry>
+                                Description
+                            </entry>
+                        </row>
+                    </thead>
+                    <tbody valign="top">
+                        <row>
+                            <entry>
+                                <literal>Default Scopes</literal>
+                            </entry>
+                            <entry>
+                                Allows you to manually specify the scopes that users must authorize when authenticating with this provider. For a complete list of scopes, please take a look at <ulink url="https://msdn.microsoft.com/en-us/library/hh243646.aspx">https://msdn.microsoft.com/en-us/library/hh243646.aspx</ulink>. By default, Keycloak uses the following scopes: <literal>wl.basic,wl.emails</literal>
+                            </entry>
+                        </row>
+                    </tbody>
+                </tgroup>
+            </table>
+        </section>
+        <section>
             <title>StackOverflow</title>
             <para>
                 To enable login with StackOverflow you first have to register an OAuth application on
@@ -1282,7 +1371,7 @@ keycloak.createLoginUrl({
     <section>
         <title>Mapping/Importing User profile data from Social Identity Provider</title>
         <para>
-            You can import user profile data provided by social identity providers like Google, GitHub, LinkedIn, Stackoverflow and Facebook 
+            You can import user profile data provided by social identity providers like Google, GitHub, LinkedIn, Microsoft, Stackoverflow and Facebook 
             into new Keycloak user created from given social accounts. After you configure a broker, you'll see a <literal>Mappers</literal>
             button appear. Click on that and you'll get to the list of mappers that are assigned to this broker. There is a
             <literal>Create</literal> button on this page. Clicking on this create button allows you to create a broker mapper.
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-microsoft.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-microsoft.html
new file mode 100755
index 0000000..a4630ac
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-microsoft.html
@@ -0,0 +1 @@
+<div data-ng-include data-src="resourceUrl + '/partials/realm-identity-provider-social.html'"></div>
\ No newline at end of file
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-microsoft-ext.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-microsoft-ext.html
new file mode 100755
index 0000000..e69de29
--- /dev/null
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/realm-identity-provider-microsoft-ext.html
diff --git a/forms/common-themes/src/main/resources/theme/base/login/login.ftl b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
index 840bf4e..388d180 100755
--- a/forms/common-themes/src/main/resources/theme/base/login/login.ftl
+++ b/forms/common-themes/src/main/resources/theme/base/login/login.ftl
@@ -70,7 +70,9 @@
             <div id="kc-social-providers">
                 <ul>
                     <#list social.providers as p>
-                        <li><a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${p.providerId}"> <span class="text">${p.alias}</span></a></li>
+                        <#assign zocialclass=p.alias>
+                        <#if zocialclass=="microsoft"><#assign zocialclass="windows"></#if>
+                        <li><a href="${p.loginUrl}" id="zocial-${p.alias}" class="zocial ${zocialclass}"> <span class="text">${p.alias}</span></a></li>
                     </#list>
                 </ul>
             </div>

pom.xml 5(+5 -0)

diff --git a/pom.xml b/pom.xml
index 06c2537..6f8d90a 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1104,6 +1104,11 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
+                <artifactId>keycloak-social-microsoft</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.keycloak</groupId>
                 <artifactId>keycloak-social-twitter</artifactId>
                 <version>${project.version}</version>
             </dependency>
diff --git a/social/microsoft/pom.xml b/social/microsoft/pom.xml
new file mode 100755
index 0000000..e32d99c
--- /dev/null
+++ b/social/microsoft/pom.xml
@@ -0,0 +1,38 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>keycloak-social-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.8.0.CR2-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+
+    <artifactId>keycloak-social-microsoft</artifactId>
+    <name>Keycloak Social Microsoft Live ID</name>
+    <description/>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-social-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-broker-oidc</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.jackson</groupId>
+            <artifactId>jackson-mapper-asl</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.jboss.logging</groupId>
+            <artifactId>jboss-logging</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftIdentityProvider.java b/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftIdentityProvider.java
new file mode 100755
index 0000000..6d84c7e
--- /dev/null
+++ b/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftIdentityProvider.java
@@ -0,0 +1,76 @@
+package org.keycloak.social.microsoft;
+
+import java.net.URLEncoder;
+
+import org.apache.commons.codec.binary.StringUtils;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.codehaus.jackson.JsonNode;
+import org.jboss.logging.Logger;
+import org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider;
+import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
+import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
+import org.keycloak.broker.oidc.util.JsonSimpleHttp;
+import org.keycloak.broker.provider.BrokeredIdentityContext;
+import org.keycloak.broker.provider.IdentityBrokerException;
+import org.keycloak.broker.provider.util.SimpleHttp;
+import org.keycloak.social.SocialIdentityProvider;
+
+
+/**
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public class MicrosoftIdentityProvider extends AbstractOAuth2IdentityProvider implements SocialIdentityProvider {
+    
+    private static final Logger log = Logger.getLogger(MicrosoftIdentityProvider.class);
+
+	public static final String AUTH_URL = "https://login.live.com/oauth20_authorize.srf";
+	public static final String TOKEN_URL = "https://login.live.com/oauth20_token.srf";
+	public static final String PROFILE_URL = "https://apis.live.net/v5.0/me";
+	public static final String DEFAULT_SCOPE = "wl.basic,wl.emails";
+
+	public MicrosoftIdentityProvider(OAuth2IdentityProviderConfig config) {
+		super(config);
+		config.setAuthorizationUrl(AUTH_URL);
+		config.setTokenUrl(TOKEN_URL);
+		config.setUserInfoUrl(PROFILE_URL);
+	}
+
+	@Override
+	protected BrokeredIdentityContext doGetFederatedIdentity(String accessToken) {
+		try {
+		    String URL = PROFILE_URL + "?access_token=" + URLEncoder.encode(accessToken,"UTF-8");
+            if (log.isDebugEnabled()) {
+                log.debug("Microsoft Live user profile request to: " + URL);
+            }
+			JsonNode profile = JsonSimpleHttp.asJson(SimpleHttp.doGet(URL));
+
+			String id = getJsonProperty(profile, "id");
+			
+			String email = null; 
+			if(profile.has("emails")){
+			    email = getJsonProperty(profile.get("emails"), "preferred");
+			}
+			
+			BrokeredIdentityContext user = new BrokeredIdentityContext(id);
+
+			user.setUsername(email!=null?email:id);
+			user.setFirstName(getJsonProperty(profile, "first_name"));
+			user.setLastName(getJsonProperty(profile, "last_name"));
+			if(email!=null)
+			  user.setEmail(email);
+			user.setIdpConfig(getConfig());
+			user.setIdp(this);
+
+			AbstractJsonUserAttributeMapper.storeUserProfileForMapper(user, profile, getConfig().getAlias());
+
+			return user;
+		} catch (Exception e) {
+			throw new IdentityBrokerException("Could not obtain user profile from Microsoft Live ID.", e);
+		}
+	}
+
+	@Override
+	protected String getDefaultScopes() {
+		return DEFAULT_SCOPE;
+	}
+}
diff --git a/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftIdentityProviderFactory.java b/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftIdentityProviderFactory.java
new file mode 100644
index 0000000..16d6960
--- /dev/null
+++ b/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftIdentityProviderFactory.java
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Copyright 2013 Red Hat, Inc. and/or its affiliates.
+ *
+ * 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.
+ */
+package org.keycloak.social.microsoft;
+
+import org.keycloak.broker.oidc.OAuth2IdentityProviderConfig;
+import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
+import org.keycloak.models.IdentityProviderModel;
+import org.keycloak.social.SocialIdentityProviderFactory;
+
+/**
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public class MicrosoftIdentityProviderFactory extends AbstractIdentityProviderFactory<MicrosoftIdentityProvider> implements SocialIdentityProviderFactory<MicrosoftIdentityProvider> {
+
+    public static final String PROVIDER_ID = "microsoft";
+
+    @Override
+    public String getName() {
+        return "Microsoft";
+    }
+
+    @Override
+    public MicrosoftIdentityProvider create(IdentityProviderModel model) {
+        return new MicrosoftIdentityProvider(new OAuth2IdentityProviderConfig(model));
+    }
+
+    @Override
+    public String getId() {
+        return PROVIDER_ID;
+    }
+}
diff --git a/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftUserAttributeMapper.java b/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftUserAttributeMapper.java
new file mode 100644
index 0000000..bee8a91
--- /dev/null
+++ b/social/microsoft/src/main/java/org/keycloak/social/microsoft/MicrosoftUserAttributeMapper.java
@@ -0,0 +1,29 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @authors tag. All rights reserved.
+ */
+package org.keycloak.social.microsoft;
+
+import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper;
+
+/**
+ * User attribute mapper.
+ * 
+ * @author Vlastimil Elias (velias at redhat dot com)
+ */
+public class MicrosoftUserAttributeMapper extends AbstractJsonUserAttributeMapper {
+
+	private static final String[] cp = new String[] { MicrosoftIdentityProviderFactory.PROVIDER_ID };
+
+	@Override
+	public String[] getCompatibleProviders() {
+		return cp;
+	}
+
+	@Override
+	public String getId() {
+		return "microsoft-user-attribute-mapper";
+	}
+
+}
diff --git a/social/microsoft/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper b/social/microsoft/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
new file mode 100755
index 0000000..d7af7f8
--- /dev/null
+++ b/social/microsoft/src/main/resources/META-INF/services/org.keycloak.broker.provider.IdentityProviderMapper
@@ -0,0 +1 @@
+org.keycloak.social.microsoft.MicrosoftUserAttributeMapper
diff --git a/social/microsoft/src/main/resources/META-INF/services/org.keycloak.social.SocialIdentityProviderFactory b/social/microsoft/src/main/resources/META-INF/services/org.keycloak.social.SocialIdentityProviderFactory
new file mode 100644
index 0000000..27b7e08
--- /dev/null
+++ b/social/microsoft/src/main/resources/META-INF/services/org.keycloak.social.SocialIdentityProviderFactory
@@ -0,0 +1 @@
+org.keycloak.social.microsoft.MicrosoftIdentityProviderFactory

social/pom.xml 1(+1 -0)

diff --git a/social/pom.xml b/social/pom.xml
index 0f0d8b8..f8685b1 100755
--- a/social/pom.xml
+++ b/social/pom.xml
@@ -21,6 +21,7 @@
         <module>twitter</module>
         <module>facebook</module>
         <module>linkedin</module>
+        <module>microsoft</module>
         <module>stackoverflow</module>
     </modules>