diff --git a/lib/commands/owner.js b/lib/commands/owner.js
index 93e0a45ad1e27..ceff5513afe64 100644
--- a/lib/commands/owner.js
+++ b/lib/commands/owner.js
@@ -59,60 +59,39 @@ class Owner extends BaseCommand {
   }
 
   async exec ([action, ...args]) {
-    const opts = {
-      ...this.npm.flatOptions,
-    }
     switch (action) {
       case 'ls':
       case 'list':
-        return this.ls(args[0], opts)
+        return this.ls(args[0])
       case 'add':
-        return this.add(args[0], args[1], opts)
+        return this.changeOwners(args[0], args[1], 'add')
       case 'rm':
       case 'remove':
-        return this.rm(args[0], args[1], opts)
+        return this.changeOwners(args[0], args[1], 'rm')
       default:
         throw this.usageError()
     }
   }
 
-  async ls (pkg, opts) {
-    if (!pkg) {
-      if (this.npm.config.get('global')) {
-        throw this.usageError()
-      }
-
-      const pkgName = await readLocalPkgName(this.npm.prefix)
-      if (!pkgName) {
-        throw this.usageError()
-      }
-
-      pkg = pkgName
-    }
-
+  async ls (pkg) {
+    pkg = await this.getPkg(pkg)
     const spec = npa(pkg)
 
     try {
-      const packumentOpts = { ...opts, fullMetadata: true }
+      const packumentOpts = { ...this.npm.flatOptions, fullMetadata: true }
       const { maintainers } = await pacote.packument(spec, packumentOpts)
       if (!maintainers || !maintainers.length) {
         this.npm.output('no admin found')
       } else {
-        this.npm.output(maintainers.map(o => `${o.name} <${o.email}>`).join('\n'))
+        this.npm.output(maintainers.map(m => `${m.name} <${m.email}>`).join('\n'))
       }
-
-      return maintainers
     } catch (err) {
       log.error('owner ls', "Couldn't get owner data", pkg)
       throw err
     }
   }
 
-  async add (user, pkg, opts) {
-    if (!user) {
-      throw this.usageError()
-    }
-
+  async getPkg (pkg) {
     if (!pkg) {
       if (this.npm.config.get('global')) {
         throw this.usageError()
@@ -122,44 +101,25 @@ class Owner extends BaseCommand {
         throw this.usageError()
       }
 
-      pkg = pkgName
+      return pkgName
     }
-    log.verbose('owner add', '%s to %s', user, pkg)
-
-    const spec = npa(pkg)
-    return this.putOwners(spec, user, opts,
-      (newOwner, owners) => this.validateAddOwner(newOwner, owners))
+    return pkg
   }
 
-  async rm (user, pkg, opts) {
+  async changeOwners (user, pkg, addOrRm) {
     if (!user) {
       throw this.usageError()
     }
 
-    if (!pkg) {
-      if (this.npm.config.get('global')) {
-        throw this.usageError()
-      }
-      const pkgName = await readLocalPkgName(this.npm.prefix)
-      if (!pkgName) {
-        throw this.usageError()
-      }
-
-      pkg = pkgName
-    }
-    log.verbose('owner rm', '%s from %s', user, pkg)
+    pkg = await this.getPkg(pkg)
+    log.verbose(`owner ${addOrRm}`, '%s to %s', user, pkg)
 
     const spec = npa(pkg)
-    return this.putOwners(spec, user, opts,
-      (rmOwner, owners) => this.validateRmOwner(rmOwner, owners))
-  }
-
-  async putOwners (spec, user, opts, validation) {
     const uri = `/-/user/org.couchdb.user:${encodeURIComponent(user)}`
-    let u = ''
+    let u
 
     try {
-      u = await npmFetch.json(uri, opts)
+      u = await npmFetch.json(uri, this.npm.flatOptions)
     } catch (err) {
       log.error('owner mutate', `Error getting user data for ${user}`)
       throw err
@@ -177,36 +137,60 @@ class Owner extends BaseCommand {
     // normalize user data
     u = { name: u.name, email: u.email }
 
-    const data = await pacote.packument(spec, { ...opts, fullMetadata: true })
+    const data = await pacote.packument(spec, { ...this.npm.flatOptions, fullMetadata: true })
 
-    // save the number of maintainers before validation for comparison
-    const before = data.maintainers ? data.maintainers.length : 0
+    const owners = data.maintainers || []
+    let maintainers
+    if (addOrRm === 'add') {
+      const existing = owners.find(o => o.name === u.name)
+      if (existing) {
+        log.info(
+          'owner add',
+          `Already a package owner: ${existing.name} <${existing.email}>`
+        )
+        return
+      }
+      maintainers = [
+        ...owners,
+        u,
+      ]
+    } else {
+      maintainers = owners.filter(o => o.name !== u.name)
 
-    const m = validation(u, data.maintainers)
-    if (!m) {
-      return
-    } // invalid owners
+      if (maintainers.length === owners.length) {
+        log.info('owner rm', 'Not a package owner: ' + u.name)
+        return false
+      }
 
-    const body = {
-      _id: data._id,
-      _rev: data._rev,
-      maintainers: m,
+      if (!maintainers.length) {
+        throw Object.assign(
+          new Error(
+            'Cannot remove all owners of a package. Add someone else first.'
+          ),
+          { code: 'EOWNERRM' }
+        )
+      }
     }
+
     const dataPath = `/${spec.escapedName}/-rev/${encodeURIComponent(data._rev)}`
-    const res = await otplease(opts, opts => {
+    const res = await otplease(this.npm.flatOptions, opts => {
       return npmFetch.json(dataPath, {
         ...opts,
         method: 'PUT',
-        body,
+        body: {
+          _id: data._id,
+          _rev: data._rev,
+          maintainers,
+        },
         spec,
       })
     })
 
     if (!res.error) {
-      if (m.length < before) {
-        this.npm.output(`- ${user} (${spec.name})`)
-      } else {
+      if (addOrRm === 'add') {
         this.npm.output(`+ ${user} (${spec.name})`)
+      } else {
+        this.npm.output(`- ${user} (${spec.name})`)
       }
     } else {
       throw Object.assign(
@@ -216,47 +200,6 @@ class Owner extends BaseCommand {
     }
     return res
   }
-
-  validateAddOwner (newOwner, owners) {
-    owners = owners || []
-    for (const o of owners) {
-      if (o.name === newOwner.name) {
-        log.info(
-          'owner add',
-          'Already a package owner: ' + o.name + ' <' + o.email + '>'
-        )
-        return false
-      }
-    }
-    return [
-      ...owners,
-      newOwner,
-    ]
-  }
-
-  validateRmOwner (rmOwner, owners) {
-    let found = false
-    const m = owners.filter(function (o) {
-      var match = (o.name === rmOwner.name)
-      found = found || match
-      return !match
-    })
-
-    if (!found) {
-      log.info('owner rm', 'Not a package owner: ' + rmOwner.name)
-      return false
-    }
-
-    if (!m.length) {
-      throw Object.assign(
-        new Error(
-          'Cannot remove all owners of a package. Add someone else first.'
-        ),
-        { code: 'EOWNERRM' }
-      )
-    }
-
-    return m
-  }
 }
+
 module.exports = Owner
diff --git a/lib/utils/otplease.js b/lib/utils/otplease.js
index 0e32493f9eb3e..566c24ef2e293 100644
--- a/lib/utils/otplease.js
+++ b/lib/utils/otplease.js
@@ -1,20 +1,17 @@
-const prompt = 'This operation requires a one-time password.\nEnter OTP:'
 const readUserInfo = require('./read-user-info.js')
 
-const isOtpError = err =>
-  err.code === 'EOTP' || (err.code === 'E401' && /one-time pass/.test(err.body))
-
 module.exports = otplease
-function otplease (opts, fn) {
-  opts = { prompt, ...opts }
-  return Promise.resolve().then(() => fn(opts)).catch(err => {
-    if (!isOtpError(err)) {
+async function otplease (opts, fn) {
+  try {
+    await fn(opts)
+  } catch (err) {
+    if (err.code !== 'EOTP' && (err.code !== 'E401' || !/one-time pass/.test(err.body))) {
       throw err
     } else if (!process.stdin.isTTY || !process.stdout.isTTY) {
       throw err
     } else {
-      return readUserInfo.otp(opts.prompt)
-        .then(otp => fn({ ...opts, otp }))
+      const otp = await readUserInfo.otp('This operation requires a one-time password.\nEnter OTP:')
+      return fn({ ...opts, otp })
     }
-  })
+  }
 }