title: Request had insufficient authentication scopes with google contacts
body: <pre><code>/* eslint-disable no-underscore-dangle */
  /* eslint-disable better-mutation/no-mutating-methods */
  
  import React, { Component } from 'react'
  import PropTypes from 'prop-types'
  import xml from 'xml-js'
  
  import Icon from './icon'
  import ButtonContent from './button-content'
  
  import { extractTitleFromEntry, extractEmailFromEntry, extractPhoneNumberFromEntry } from './utils'
  
  const SCOPE = 'https://www.googleapis.com/auth/spreadsheets.readonly'
  const MAX_RESULTS = '999' // TODO Make this parametable or paginate
  class GoogleContacts extends Component {
    constructor(props) {
      super(props)
      this.signIn = this.signIn.bind(this)
      this.handleImportContacts = this.handleImportContacts.bind(this)
      this.handleParseContacts = this.handleParseContacts.bind(this)
      this.state = {
        hovered: false,
        active: false
      }
    }
  
    componentDidMount() {
      const { jsSrc } = this.props
      ;((d, s, id, cb) =&gt; {
        const element = d.getElementsByTagName(s)[0]
        const fjs = element
        let js = element
        js = d.createElement(s)
        js.id = id
        js.src = jsSrc
        if (fjs &amp;&amp; fjs.parentNode) {
          fjs.parentNode.insertBefore(js, fjs)
        } else {
          d.head.appendChild(js)
        }
        js.onload = cb
      })(document, 'script', 'google-contacts')
    }
  
    handleImportContacts(res) {
      const { onFailure } = this.props
  
      if (res) {
        const authResponse = res.getAuthResponse();
        window.gapi.load('client', () =&gt; {
          window.gapi.client
            .request({
              path: '/m8/feeds/contacts/full',
              params: { 'max-results': MAX_RESULTS},
              headers: {
                'GData-Version': '3.0',
                Authorization: `Bearer ${authResponse.access_token}`
              }
            })
            .then(response =&gt; this.handleParseContacts(response), err =&gt; onFailure(err))
        })
      }
    }
  
    handleParseContacts(response) {
      const { onSuccess } = this.props
  
      // Now let's parse the XML...
      const options = { ignoreDeclaration: true, ignoreComment: true, compact: true }
      const parsed = xml.xml2js(response.body, options)
  
      // Iterate over each contact.
      const results = []
  
      Object.keys(parsed.feed.entry).forEach(key =&gt; {
        if (
          parsed.feed.entry[key] &amp;&amp;
          parsed.feed.entry[key]['gd:email'] &amp;&amp;
          parsed.feed.entry[key]['gd:email']._attributes &amp;&amp;
          parsed.feed.entry[key]['gd:email']._attributes.address
        ) {
          results.push({
            title: extractTitleFromEntry(parsed.feed.entry[key]),
            email: extractEmailFromEntry(parsed.feed.entry[key]),
            phoneNumber: extractPhoneNumberFromEntry(parsed.feed.entry[key])
          })
        }
      })
  
      onSuccess(results)
    }
  
    signIn(e) {
      const {
        clientId,
        cookiePolicy,
        loginHint,
        hostedDomain,
        redirectUri,
        discoveryDocs,
        onRequest,
        onFailure,
        uxMode,
        accessType,
        responseType,
        prompt,
        onSuccess
      } = this.props
  
      const params = {
        client_id: clientId,
        cookie_policy: cookiePolicy,
        login_hint: loginHint,
        hosted_domain: hostedDomain,
        discoveryDocs,
        ux_mode: uxMode,
        redirect_uri: redirectUri,
        scope: SCOPE,
        access_type: accessType
      }
  
      if (responseType === 'code') {
        params.access_type = 'offline'
      }
  
      if (e) {
        e.preventDefault() // to prevent submit if used within form
      }
      if (!this.state.disabled) {
        const _signIn = () =&gt; {
          const auth2 = window.gapi.auth2.getAuthInstance()
          const options = { prompt }
          onRequest()
          if (responseType === 'code') {
            auth2.grantOfflineAccess(options).then(res =&gt; onSuccess(res), err =&gt; onFailure(err))
          } else {
            auth2.signIn(options).then(res =&gt; this.handleImportContacts(res), err =&gt; onFailure(err))
          }
        }
  
        window.gapi.load('auth2', () =&gt; {
          if (!window.gapi.auth2.getAuthInstance()) {
            window.gapi.auth2.init(params).then(_signIn)
          } else {
            _signIn()
          }
        })
      }
    }
  
    render() {
      const { tag, type, className, disabledStyle, buttonText, children, render, theme, icon } = this.props
      const disabled = this.state.disabled || this.props.disabled
  
      if (render) {
        return render({ onClick: this.signIn })
      }
  
      const initialStyle = {
        backgroundColor: theme === 'dark' ? 'rgb(66, 133, 244)' : '#fff',
        display: 'inline-flex',
        alignItems: 'center',
        color: theme === 'dark' ? '#fff' : 'rgba(0, 0, 0, .54)',
        boxShadow: '0 2px 2px 0 rgba(0, 0, 0, .24), 0 0 1px 0 rgba(0, 0, 0, .24)',
        padding: 0,
        borderRadius: 2,
        border: '1px solid transparent',
        fontSize: 14,
        fontWeight: '500',
        fontFamily: 'Roboto, sans-serif'
      }
  
      const hoveredStyle = {
        cursor: 'pointer',
        opacity: 0.9
      }
  
      const activeStyle = {
        cursor: 'pointer',
        backgroundColor: theme === 'dark' ? '#3367D6' : '#eee',
        color: theme === 'dark' ? '#fff' : 'rgba(0, 0, 0, .54)',
        opacity: 1
      }
  
      const defaultStyle = (() =&gt; {
        if (disabled) {
          return Object.assign({}, initialStyle, disabledStyle)
        }
  
        if (this.state.active) {
          if (theme === 'dark') {
            return Object.assign({}, initialStyle, activeStyle)
          }
  
          return Object.assign({}, initialStyle, activeStyle)
        }
  
        if (this.state.hovered) {
          return Object.assign({}, initialStyle, hoveredStyle)
        }
  
        return initialStyle
      })()
      const googleLoginButton = React.createElement(
        tag,
        {
          onMouseEnter: () =&gt; this.setState({ hovered: true }),
          onMouseLeave: () =&gt; this.setState({ hovered: false, active: false }),
          onMouseDown: () =&gt; this.setState({ active: true }),
          onMouseUp: () =&gt; this.setState({ active: false }),
          onClick: this.signIn,
          style: defaultStyle,
          type,
          disabled,
          className
        },
        [
          icon &amp;&amp; &lt;Icon key={1} active={this.state.active} /&gt;,
          &lt;ButtonContent icon={icon} key={2}&gt;
            {children || buttonText}
          &lt;/ButtonContent&gt;
        ]
      )
  
      return googleLoginButton
    }
  }
  
  
  export default GoogleContacts
  
  </code></pre>
  
  <p>In React project I need to login with gamil and get contacts of user I found package called Googlecontacts.This is code of the GoogleContacts package to get contacts from Google API, But I'm getting the 403 error. This error shows that my scope is wrong! I tried a lot of scopes but I coudn't get contacts of gamil. What is the right scope for google contacts?</p>