diff --git a/app/controllers/import/bitbucket_controller.rb b/app/controllers/import/bitbucket_controller.rb
index 6ea54744da83982edbd0633bb7e86632e6aa2a96..ee30a24ab771952af7e3284bb662d11dcb655dd3 100644
--- a/app/controllers/import/bitbucket_controller.rb
+++ b/app/controllers/import/bitbucket_controller.rb
@@ -3,49 +3,54 @@ class Import::BitbucketController < Import::BaseController
   before_action :bitbucket_auth, except: :callback
 
   rescue_from OAuth::Error, with: :bitbucket_unauthorized
-  rescue_from Gitlab::BitbucketImport::Client::Unauthorized, with: :bitbucket_unauthorized
+  rescue_from Bitbucket::Error::Unauthorized, with: :bitbucket_unauthorized
 
   def callback
-    request_token = session.delete(:oauth_request_token)
-    raise "Session expired!" if request_token.nil?
+    response = client.auth_code.get_token(params[:code], redirect_uri: callback_import_bitbucket_url)
 
-    request_token.symbolize_keys!
-
-    access_token = client.get_token(request_token, params[:oauth_verifier], callback_import_bitbucket_url)
-
-    session[:bitbucket_access_token] = access_token.token
-    session[:bitbucket_access_token_secret] = access_token.secret
+    session[:bitbucket_token]         = response.token
+    session[:bitbucket_expires_at]    = response.expires_at
+    session[:bitbucket_expires_in]    = response.expires_in
+    session[:bitbucket_refresh_token] = response.refresh_token
 
     redirect_to status_import_bitbucket_url
   end
 
   def status
-    @repos = client.projects
-    @incompatible_repos = client.incompatible_projects
+    client = Bitbucket::Client.new(credentials)
+    repos  = client.repos
+
+    @repos = repos.select(&:valid?)
+    @incompatible_repos = repos.reject(&:valid?)
 
-    @already_added_projects = current_user.created_projects.where(import_type: "bitbucket")
+    @already_added_projects = current_user.created_projects.where(import_type: 'bitbucket')
     already_added_projects_names = @already_added_projects.pluck(:import_source)
 
-    @repos.to_a.reject!{ |repo| already_added_projects_names.include? "#{repo["owner"]}/#{repo["slug"]}" }
+    @repos.to_a.reject! { |repo| already_added_projects_names.include?(repo.full_name) }
   end
 
   def jobs
-    jobs = current_user.created_projects.where(import_type: "bitbucket").to_json(only: [:id, :import_status])
-    render json: jobs
+    render json: current_user.created_projects
+                             .where(import_type: 'bitbucket')
+                             .to_json(only: [:id, :import_status])
   end
 
   def create
+    client = Bitbucket::Client.new(credentials)
+
     @repo_id = params[:repo_id].to_s
-    repo = client.project(@repo_id.gsub('___', '/'))
-    @project_name = repo['slug']
-    @target_namespace = find_or_create_namespace(repo['owner'], client.user['user']['username'])
+    name = @repo_id.to_s.gsub('___', '/')
+    repo = client.repo(name)
+    @project_name = repo.name
 
-    unless Gitlab::BitbucketImport::KeyAdder.new(repo, current_user, access_params).execute
-      render 'deploy_key' and return
-    end
+    repo_owner = repo.owner
+    repo_owner = current_user.username if repo_owner == client.user.username
+    @target_namespace = params[:new_namespace].presence || repo_owner
+
+    namespace = find_or_create_namespace(target_namespace_name, repo_owner)
 
     if current_user.can?(:create_projects, @target_namespace)
-      @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, @target_namespace, current_user, access_params).execute
+      @project = Gitlab::BitbucketImport::ProjectCreator.new(repo, namespace, current_user, credentials).execute
     else
       render 'unauthorized'
     end
@@ -54,8 +59,15 @@ class Import::BitbucketController < Import::BaseController
   private
 
   def client
-    @client ||= Gitlab::BitbucketImport::Client.new(session[:bitbucket_access_token],
-                                                    session[:bitbucket_access_token_secret])
+    @client ||= OAuth2::Client.new(provider.app_id, provider.app_secret, options)
+  end
+
+  def provider
+    Gitlab.config.omniauth.providers.find { |provider| provider.name == 'bitbucket' }
+  end
+
+  def options
+    OmniAuth::Strategies::Bitbucket.default_options[:client_options].deep_symbolize_keys
   end
 
   def verify_bitbucket_import_enabled
@@ -63,26 +75,23 @@ class Import::BitbucketController < Import::BaseController
   end
 
   def bitbucket_auth
-    if session[:bitbucket_access_token].blank?
-      go_to_bitbucket_for_permissions
-    end
+    go_to_bitbucket_for_permissions if session[:bitbucket_token].blank?
   end
 
   def go_to_bitbucket_for_permissions
-    request_token = client.request_token(callback_import_bitbucket_url)
-    session[:oauth_request_token] = request_token
-
-    redirect_to client.authorize_url(request_token, callback_import_bitbucket_url)
+    redirect_to client.auth_code.authorize_url(redirect_uri: callback_import_bitbucket_url)
   end
 
   def bitbucket_unauthorized
     go_to_bitbucket_for_permissions
   end
 
-  def access_params
+  def credentials
     {
-      bitbucket_access_token: session[:bitbucket_access_token],
-      bitbucket_access_token_secret: session[:bitbucket_access_token_secret]
+      token: session[:bitbucket_token],
+      expires_at: session[:bitbucket_expires_at],
+      expires_in: session[:bitbucket_expires_in],
+      refresh_token: session[:bitbucket_refresh_token]
     }
   end
 end
diff --git a/app/views/import/bitbucket/status.html.haml b/app/views/import/bitbucket/status.html.haml
index f8b4b107513991c0005964c2f416ab545332b49f..e62ff5f61f6bb3a057cdae3e42555b01881cfe0c 100644
--- a/app/views/import/bitbucket/status.html.haml
+++ b/app/views/import/bitbucket/status.html.haml
@@ -1,5 +1,6 @@
-- page_title "Bitbucket import"
-- header_title "Projects", root_path
+- page_title 'Bitbucket import'
+- header_title 'Projects', root_path
+
 %h3.page-title
   %i.fa.fa-bitbucket
   Import projects from Bitbucket
@@ -10,13 +11,13 @@
   %hr
   %p
   - if @incompatible_repos.any?
-    = button_tag class: "btn btn-import btn-success js-import-all" do
+    = button_tag class: 'btn btn-import btn-success js-import-all' do
       Import all compatible projects
-      = icon("spinner spin", class: "loading-icon")
+      = icon('spinner spin', class: 'loading-icon')
   - else
-    = button_tag class: "btn btn-success js-import-all" do
+    = button_tag class: 'btn btn-success js-import-all' do
       Import all projects
-      = icon("spinner spin", class: "loading-icon")
+      = icon('spinner spin', class: 'loading-icon')
 
 .table-responsive
   %table.table.import-jobs
@@ -32,7 +33,7 @@
       - @already_added_projects.each do |project|
         %tr{id: "project_#{project.id}", class: "#{project_status_css_class(project.import_status)}"}
           %td
-            = link_to project.import_source, "https://bitbucket.org/#{project.import_source}", target: "_blank"
+            = link_to project.import_source, 'https://bitbucket.org/#{project.import_source}', target: '_blank'
           %td
             = link_to project.path_with_namespace, [project.namespace.becomes(Namespace), project]
           %td.job-status
@@ -47,31 +48,31 @@
               = project.human_import_status_name
 
       - @repos.each do |repo|
-        %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
+        %tr{id: "repo_#{repo.owner}___#{repo.slug}"}
           %td
-            = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
+            = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: "_blank"
           %td.import-target
-            = import_project_target(repo['owner'], repo['slug'])
+            = "#{repo.full_name}"
           %td.import-actions.job-status
-            = button_tag class: "btn btn-import js-add-to-import" do
+            = button_tag class: 'btn btn-import js-add-to-import' do
               Import
-              = icon("spinner spin", class: "loading-icon")
+              = icon('spinner spin', class: 'loading-icon')
       - @incompatible_repos.each do |repo|
-        %tr{id: "repo_#{repo["owner"]}___#{repo["slug"]}"}
+        %tr{id: "repo_#{repo.owner}___#{repo.slug}"}
           %td
-            = link_to "#{repo["owner"]}/#{repo["slug"]}", "https://bitbucket.org/#{repo["owner"]}/#{repo["slug"]}", target: "_blank"
+            = link_to "#{repo.full_name}", "https://bitbucket.org/#{repo.full_name}", target: '_blank'
           %td.import-target
           %td.import-actions-job-status
-            = label_tag "Incompatible Project", nil, class: "label label-danger"
+            = label_tag 'Incompatible Project', nil, class: 'label label-danger'
 
 - if @incompatible_repos.any?
   %p
     One or more of your Bitbucket projects cannot be imported into GitLab
     directly because they use Subversion or Mercurial for version control,
     rather than Git. Please convert
-    = link_to "them to Git,", "https://www.atlassian.com/git/tutorials/migrating-overview"
+    = link_to 'them to Git,', 'https://www.atlassian.com/git/tutorials/migrating-overview'
     and go through the
-    = link_to "import flow", status_import_bitbucket_path, "data-no-turbolink" => "true"
+    = link_to 'import flow', status_import_bitbucket_path, 'data-no-turbolink' => 'true'
     again.
 
 .js-importer-status{ data: { jobs_import_path: "#{jobs_import_bitbucket_path}", import_path: "#{import_bitbucket_path}" } }
diff --git a/lib/bitbucket/error/unauthorized.rb b/lib/bitbucket/error/unauthorized.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5e2eb57bb0ee37dad8158dcaf6bcf001e5e0ebf4
--- /dev/null
+++ b/lib/bitbucket/error/unauthorized.rb
@@ -0,0 +1,6 @@
+module Bitbucket
+  module Error
+    class Unauthorized < StandardError
+    end
+  end
+end