generate_refresh_token.sh 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. #!/bin/bash
  2. # Copyright 2019 Google
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. # Generates a refresh token for a Google account, associated with a Firebase
  16. # project. Requires curl, xmllint and jq.
  17. #
  18. # To revoke the refresh token, go to myaccount.google.com/permissions, find the
  19. # Firebase project, and click 'remove access'.
  20. #
  21. # Usage:
  22. # ./generate_refresh_token.sh path/to/GoogleService-Info.plist
  23. set -o nounset
  24. set -o errexit
  25. # Redirect uri must be consistent across all calls in the oauth flow. This
  26. # special value indicates an out-of-band uri, which the user will be expected
  27. # to copy+paste into their browser.
  28. readonly REDIRECT_URI="urn:ietf:wg:oauth:2.0:oob"
  29. main() {
  30. if [[ $# != 1 ]] ; then
  31. echo "Usage:" >&2
  32. echo " $0 path/to/GoogleService-Info.plist" >&2
  33. exit 1
  34. fi
  35. declare -r PLIST_PATH="$1"
  36. declare -r client_id=$(parse_plist "${PLIST_PATH}" "CLIENT_ID")
  37. declare -r reversed_client_id=$(parse_plist "${PLIST_PATH}" "REVERSED_CLIENT_ID")
  38. declare -r location=$(get_location "${client_id}")
  39. echo "Go to the following URL and complete the login flow:"
  40. echo "${location}"
  41. echo ""
  42. declare code=""
  43. read -p "Paste the resulting code here: " code
  44. echo ""
  45. echo "Refresh token: " $(get_refresh_token "${client_id}" "${code}")
  46. }
  47. # Parse a plist file (specifically, a GoogleService-Info.plist file) are return
  48. # the value for the indicated key.
  49. #
  50. # Arguments:
  51. # plist: String. Path to the plist file.
  52. # key: String. Key value to lookup in the dictionary of the plist file.
  53. parse_plist() {
  54. local plist="$1"
  55. local key="$2"
  56. readonly XPATH_TEMPLATE="/plist/dict/key[.='%s']/following-sibling::string[1]/text()"
  57. xmllint --xpath $(printf "${XPATH_TEMPLATE}" "${key}") "${plist}"
  58. }
  59. # Fetches the uri location used to generate a login code. The user will be
  60. # expected to copy+paste this into the url bar in their browser.
  61. #
  62. # Arguments:
  63. # client_id: String. The id of the app to authenticate against. In the case
  64. # of firebase apps, this probably looks like
  65. # "1234567890-alpha123numeric456.apps.googleusercontent.com"
  66. get_location() {
  67. declare -r client_id="$1"
  68. curl --silent --show-error --include --get \
  69. --data-urlencode "client_id=${client_id}" \
  70. --data-urlencode "redirect_uri=${REDIRECT_URI}" \
  71. --data-urlencode "response_type=code" \
  72. --data-urlencode "scope=openid profile email" \
  73. "https://accounts.google.com/o/oauth2/v2/auth" \
  74. | grep '^location: ' \
  75. | sed -e 's/^location: //'
  76. }
  77. # Fetches the refresh token based on the oauth code generated in the browser.
  78. # Note that the code generated in the browser is only valid for a short period
  79. # of time; this function will fail if the code is expired.
  80. #
  81. # Arguments:
  82. # client_id: String. The id of the app to authenticate against. In the case
  83. # of firebase apps, this probably looks like
  84. # "1234567890-alpha123numeric456.apps.googleusercontent.com"
  85. # code: String. The oauth code generated in the browser by the user.
  86. get_refresh_token() {
  87. declare -r client_id="$1"
  88. declare -r code="$2"
  89. curl --silent --show-error -X POST \
  90. --data-urlencode "client_id=${client_id}" \
  91. --data-urlencode "code=${code}" \
  92. --data-urlencode "redirect_uri=${REDIRECT_URI}" \
  93. --data-urlencode "grant_type=authorization_code" \
  94. "https://www.googleapis.com/oauth2/v4/token" \
  95. | jq -r ".refresh_token"
  96. }
  97. main "$@"