質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
87.20%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

OpenID

OpenIDは、様々なWebサイトで 1つのID情報のみで認証が可能にするサービスです。

解決済

sns認証にて(主にlineで)id_tokenからemail取得ができない

yaharu
yaharu

総合スコア1

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

OpenID

OpenIDは、様々なWebサイトで 1つのID情報のみで認証が可能にするサービスです。

1回答

0評価

0クリップ

340閲覧

投稿2021/11/17 08:10

###質問
railsでline認証を行っています。そこで、id_tokenからemailも取得したいのですが取得できません。以下のコードでどこが間違っているのでしょうか。また、以下のようにputsで出力してもherokuのログに出力がされません。そこもできれば教えていただけると助かります。
###コード
model/user.rb

require 'uri' require 'net/http' class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: [:facebook, :line] has_many :posts has_many :likes has_many :post_likes, through: :likes, source: :post mount_uploader :user_image, ImageUploader validates :username, {uniqueness: true, presence: true, length: {maximum: 15}} def self.find_for_oauth(auth, code) id_token_payload_email = User.get_access_token(code) unless id_token_payload_email #クライアントアプリにemail取得をユーザが許可していない場合 return id_token_payload_email = User.dummy_email(auth) end user = User.where(uid: auth.uid, provider: auth.provider).first if user == nil user = User.new( uid: auth.uid, provider: auth.provider, email: id_token_payload_email, username: auth.info.name, password: Devise.friendly_token[0, 20]#開発者にも分からないようにランダムなパスワードが作られる。 ) elsif user.provider == nil #userアカウント持っていて途中からsns認証使う場合 user = User.new( uid: auth.uid, provider: auth.provider ) end user.skip_confirmation! user.save user end def self.get_access_token(code) uri = URI.parse("https://api.line.me/oauth2/v2.1/token")#アクセストークン取得。この際に、同じハッシュにid_tokenも含まれる request = Net::HTTP::Post.new(uri) request.content_type = "application/x-www-form-urlencoded" request.set_form_data( "client_id" => ENV["LINE_APP_ID"], "client_secret" => ENV["LINE_APP_SECRET"], "code" => "#{code}", "grant_type" => "authorization_code", "redirect_uri" => "https://spot-share-site.herokuapp.com//users/sign_up", ) req_options = { use_ssl: uri.scheme == "https", } response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http| http.request(request) end id_token = JSON.parse(response.body)["id_token"] puts id_token id_token_payload = User.get_id_token(id_token) return id_token_payload[:email] end def self.get_id_token(id_token) uri = URI.parse("https://api.line.me/oauth2/v2.1/verify") #id_tokenの中身を取得(ペイロード部) request = Net::HTTP::Post.new(uri) request.content_type = "application/x-www-form-urlencoded" request.set_form_data( client_id: ENV["LINE_APP_ID"], id_token: id_token ) req_options = { use_ssl: uri.scheme == "https", } response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http| http.request(request) end puts response return response end def self.dummy_email(auth) return "#{auth.uid}-#{auth.provider}@example.com" end end

controller/users/omniauth_callbacks_controller

# frozen_string_literal: true class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController # You should configure your model like this: # devise :omniauthable, omniauth_providers: [:twitter] # You should also create an action method in this controller like this: # def twitter # end # More info at: # https://github.com/heartcombo/devise#omniauth # GET|POST /resource/auth/twitter # def passthru # super # end # GET|POST /users/auth/twitter/callback # def failure # super # end # protected # The path used when OmniAuth fails # def after_omniauth_failure_path_for(scope) # super(scope) # end def facebook callback_from :facebook end def line callback_from :line end private def callback_from(provider) provider = provider.to_s code = params[:code] @user = User.find_for_oauth(request.env['omniauth.auth'], code) if @user.persisted? flash[:notice] = I18n.t('devise.omniauth_callbacks.success', kind: provider.capitalize) sign_in_and_redirect @user, event: :authentication #sign_in(:user, @user) else session["devise.#{provider}_data"] = request.env['omniauth.auth'] redirect_to new_user_registration_url end def failure redirect_to root_path end end end

色々調べると、initializer/omniauthにてomniauthをオーバライドしてopenidconnectを実装している人が多かったです。しかし、上記のコードでemailが取得できない理由が分かりません。どうか宜しくお願い致します。

###試したこと
ログを見てみると、emailにはdummy_emailで生成されたメールアドレスが入っていたのでid_tokenのペイロード部にemailがなかったかそもそもアクセストークン取得やペイロード部取得のhttp通信がうまくいっていないか。そこで、よく見ると#Net::HTTPBadRequest:0x0000562b9349bd48と返ってきてました。

###参考
https://developers.line.biz/en/reference/line-login/#refresh-access-token
###環境
Ruby version 2.7.3

Rails version 6.1.4.1

良い質問の評価を上げる

以下のような質問は評価を上げましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

  • プログラミングに関係のない質問
  • やってほしいことだけを記載した丸投げの質問
  • 問題・課題が含まれていない質問
  • 意図的に内容が抹消された質問
  • 過去に投稿した質問と同じ内容の質問
  • 広告と受け取られるような投稿

評価を下げると、トップページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

yaharu

2021/11/17 09:15

修正依頼ありがとうございます。

まだ回答がついていません

会員登録して回答してみよう

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
87.20%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

OpenID

OpenIDは、様々なWebサイトで 1つのID情報のみで認証が可能にするサービスです。