diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index 59a4d1f..e48dfe7 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -103,6 +103,10 @@ production: &base
     bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
     password: '_the_password_of_the_bind_user'
     allow_username_or_email_login: true
+    mapping:
+      name: 'cn'
+      username: 'uid'
+      email: 'mail'
 
   ## OmniAuth settings
   omniauth:
@@ -131,7 +135,14 @@ production: &base
       # - { name: 'github', app_id: 'YOUR APP ID',
       #     app_secret: 'YOUR APP SECRET' }
 
-
+  ## User Mapping Procs
+  # These procs allow for custom mapping of user information from LDAP / Omniauth
+  # onto your user model.
+  #
+  # user_mapping:
+  #  name: ->(auth) { auth.info.name.to_s }
+  #  username: ->(auth) { auth.info.email.to_s.downcase.match(/^[^@]*/)[0] }
+  #  email: ->(auth) { auth.info.email.to_s.downcase }
 
   #
   # 3. Advanced settings
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index e0207c6..c079cc4 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -36,6 +36,7 @@ end
 
 # Default settings
 Settings['ldap'] ||= Settingslogic.new({})
+Settings.ldap['mapping'] ||= Settingslogic.new({})
 Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
 Settings.ldap['allow_username_or_email_login'] = false if Settings.ldap['allow_username_or_email_login'].nil?
 
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index de70c5c..bea8191 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -33,13 +33,14 @@ module Gitlab
     def create_from_omniauth(auth, ldap = false)
       provider = auth.provider
       uid = auth.info.uid || auth.uid
-      uid = uid.to_s.force_encoding("utf-8")
-      name = auth.info.name.to_s.force_encoding("utf-8")
-      email = auth.info.email.to_s.downcase unless auth.info.email.nil?
+      uid = uid.to_s.force_encoding('utf-8')
+      name = extract(:name, auth, ldap).force_encoding('utf-8')
+      username = extract(:username, auth, ldap).force_encoding('utf-8')
+      email = extract(:email, auth, ldap).force_encoding('utf-8')
 
       ldap_prefix = ldap ? '(LDAP) ' : ''
       raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
-        " address" if auth.info.email.blank?
+        " address" if email.blank?
 
       log.info "#{ldap_prefix}Creating user from #{provider} login"\
         " {uid => #{uid}, name => #{name}, email => #{email}}"
@@ -48,7 +49,7 @@ module Gitlab
         extern_uid: uid,
         provider: provider,
         name: name,
-        username: email.match(/^[^@]*/)[0],
+        username: username,
         email: email,
         password: password,
         password_confirmation: password,
@@ -101,5 +102,31 @@ module Gitlab
     def ldap_conf
       @ldap_conf ||= Gitlab.config.ldap
     end
+
+    private
+
+    def extract(field_name, auth, ldap = false)
+      @ldap_mapper ||= Gitlab.config.ldap.mapping rescue Hash.new
+      @mapper ||= begin
+        defaults = {
+          name: ->(auth) { auth.info.name.to_s },
+          username: ->(auth) { auth.info.email.to_s.downcase.match(/^[^@]*/)[0] },
+          email: ->(auth) { auth.info.email.to_s.downcase },
+        }
+        extras = Gitlab.config.user_mapping rescue Hash.new
+        defaults.merge(extras)
+      end
+
+      if ldap && !@ldap_mapper[field_name].nil?
+        begin
+          ldap_attr = @ldap_mapper[field_name].to_sym
+          Array(auth.extra.raw_info[ldap_attr])[0]
+        rescue
+          raise "(LDAP) Failed to get '#{@ldap_mapper[field_name]}' for #{field_name} for #{auth.info.uid}"
+        end
+      else
+        @mapper[field_name].call(auth)
+      end
+    end
   end
 end
diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb
index 903d276..cf9e7b7 100644
--- a/spec/lib/auth_spec.rb
+++ b/spec/lib/auth_spec.rb
@@ -4,7 +4,7 @@ describe Gitlab::Auth do
   let(:gl_auth) { Gitlab::Auth.new }
 
   before do
-    Gitlab.config.stub(omniauth: {})
+    Gitlab.config.stub(omniauth: {}, ldap: {})
 
     @info = mock(
       uid: '12djsak321',
@@ -74,9 +74,22 @@ describe Gitlab::Auth do
   end
 
   describe :create_from_omniauth do
+    before do
+      @raw_info = {
+        cn: 'John Black',
+        mail: [ 'john.black@email.com' ],
+        nickname: 'jonny'
+      }
+
+      @ldap_auth = mock(
+        info: @info,
+        extra: mock(raw_info: @raw_info),
+        provider: 'ldap'
+      )
+    end
+
     it "should create user from LDAP" do
-      @auth = mock(info: @info, provider: 'ldap')
-      user = gl_auth.create_from_omniauth(@auth, true)
+      user = gl_auth.create_from_omniauth(@ldap_auth, true)
 
       user.should be_valid
       user.extern_uid.should == @info.uid
@@ -92,9 +105,59 @@ describe Gitlab::Auth do
       user.provider.should == 'twitter'
     end
 
+    it "should still import without extra mapping" do
+      Gitlab.config.stub(omniauth: {})
+      user = gl_auth.create_from_omniauth(@ldap_auth, true)
+
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.provider.should == 'ldap'
+    end
+
+    it "should have user details from procs" do
+      Gitlab.config.stub(omniauth: {}, user_mapping: {})
+      Gitlab.config.user_mapping[:name] = ->(auth) { 'TestName' }
+      Gitlab.config.user_mapping[:email] = ->(auth) { 'email@somewhere.com' }
+      Gitlab.config.user_mapping[:username] = ->(auth) { 'TestUsername' }
+
+      user = gl_auth.create_from_omniauth(@ldap_auth, true)
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.name.should == 'TestName'
+      user.email.should == 'email@somewhere.com'
+      user.username.should == 'TestUsername'
+    end
+
+    it "should modify value using proc" do
+      Gitlab.config.stub(omniauth: {}, user_mapping: {})
+      Gitlab.config.user_mapping[:username] = ->(auth) { auth.info.email.to_s.downcase.split('@').first }
+
+      user = gl_auth.create_from_omniauth(@ldap_auth, true)
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.username.should == 'john'
+    end
+
+    it "should be able to use raw ldap information through simple ldap mapping" do
+      Gitlab.config.ldap.stub(mapping: { name: 'cn', email: 'mail' })
+
+      user = gl_auth.create_from_omniauth(@ldap_auth, true)
+      user.should be_valid
+      user.extern_uid.should == @info.uid
+      user.name.should == 'John Black'
+      user.email.should == 'john.black@email.com'
+    end
+
+    it "should raise an error if an invalid field is in ldap mapping" do
+      Gitlab.config.ldap.stub(mapping: { name: 'invalid' })
+
+      expect {
+        gl_auth.create_from_omniauth(@ldap_auth, true)
+      }.to raise_error
+    end
+
     it "should apply defaults to user" do
-      @auth = mock(info: @info, provider: 'ldap')
-      user = gl_auth.create_from_omniauth(@auth, true)
+      user = gl_auth.create_from_omniauth(@ldap_auth, true)
 
       user.should be_valid
       user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit