[Flutter] Firebase Auth와 LINE SDK를 사용하여 LINE 로그인

이마


Firebase Auth와 LINE SDK를 사용하여 Flutter 응용 프로그램에서 LINE 로그인을 구현했습니다.
Firebase×LINE 사용이 많지 않은지 정보가 많지 않아 고전하는 만큼 참고 정도의 절차를 적어야 한다.
나는 이것이 최선의 실천인지 아닌지에 대해 자신이 없다. 만약 당신의 건의와 건의가 있다면, 나는 당신의 평론을 받게 되어 매우 기쁠 것이다.

개략


LINE 로그인은 Firebase Auth가 공식적으로 대응하지 않기 때문에 Firebase의 사용자 정의 인증 형식으로 이루어집니다.
맞춤형 인증은 맞춤형 영패가 필요하지만, 응용 프로그램 (Flutter) 측면에서 생성할 수 없기 때문에 클라우드 펀션도 맞춤형 영패를 얻는 데 사용됩니다.

화상도



로그인 화면 만들기


각종 로그인 처리를 실시하기 전에 먼저 간단하게 로그인 화면을 제작한다.
firebase_auth의 상세한 내용은 잠시 언급하지 않고, 전제는 이미 포장이 설치되어 있다는 것이다.
참고로 이번에는 상태 관리flutter_riverpod에서 View와 논리 분리를 사용했다.
파일 구성은 다음과 같습니다.
lib/
 ├ main.dart
 └ app/
    ├ sign_in/
    │  └ sign_in_page.dart (View)
    │
    └ auth_manager/
       └ auth_manager.dart (ロジック)
평소에는 MVM을 많이 사용하지만, 이번에는 늘 분리된 정도라고 생각하니, 구조를 너무 참고하지 마세요.sign_in_page.dart의 코드는 다음과 같다.Sign In 단추만 있는 간단한 화면에서 단추 클릭auth_manager.dart(내용 후술)을 통해 로그인 처리를 호출합니다.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../auth_manager/auth_manager.dart';

class SignInPage extends ConsumerWidget {
  const SignInPage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
      body: Center(
        child: ElevatedButton(
          onPressed: () => 
		  ref.read(authManagerProvider).signInWithLine(),
          child: const Text('Sign In with LINE'),
        ),
      ),
    );
  }
auth_manager.dart의 내용은 다음과 같다.
이번 라인 로그인과는 직접적인 관련이 없지만 로그인 상태를 판정하는 처리도 기술했다.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

final authManagerProvider = ChangeNotifierProvider<AuthManager>(
  (ref) {
    return AuthManager();
  },
);

class AuthManager with ChangeNotifier {
  AuthManager() {
    _firebaseAuth.authStateChanges().listen((user) {
      isLoggedIn = user != null;
      notifyListeners();
    });
  }
  final _firebaseAuth = FirebaseAuth.instance;
  bool isLoggedIn = false;
   
  Future<void> signInWithLine() async {
    // 後ほどここにログイン処理を実装していく
  }
}

LINE 로그인 설치


LINE Developers 채널 만들기


LINE 로그인을 수행하려면 LINE Developers 채널을 미리 만들어야 합니다.
LINE Developer 로그인은 오래전에 이미 한 것이어서 기억이 흐려져서 사랑을 끊는다.

채널 생성


LINE Developer 로그인이 완료되면 이 페이지의今すぐはじめよう를 클릭하여 제작합니다.

필요한 사항을 입력하십시오.
입력한 정보는 편집할 수 있고 망설이면 돼요.



참고로 채널 이름과 채널 설명은 로그인할 때 다음과 같습니다.
채널 아이콘도 여기에 표시될 수 있습니다.
(그림은 안드로이드)

채널 생성 완료


제작이 완료되면 채널의 설정 내용을 표시합니다.
잠시 후 여기서 확인할 수 있는 채널 ID를 사용할 예정이니 미리 적어두세요.

LINE 로그인 설정


LINE 로그인 설정을 켜고 iOS>iOS bundle ID, Android>パッケージ名를 각각 설정합니다.
(확인 방법은 다음과 같다)

iOS의 iOS bundle ID


다음 명령을 사용하여 XCode 열기Runner>General>bundle Identifier 확인
$ open ios/Runner.xcworkspace/

안드로이드 패키지 이름

android/app/src/main/AndroidManifest.xml의 첫머리에 쓰여 있다
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="your_package_name">

LINE SDK for Fluter 가져오기


지금까지 LINE Developers의 설정이 끝났기 때문에 응용 프로그램으로 돌아갑니다.
응용 프로그램에서 LINE에 로그인하려면 LINE SDK를 가져올 필요가 있습니다.
우선 추가큰 가방.

iOS 설정


큰 가방의 Readme를 참조하여 ios/Runner/Info.plist에 다음과 같은 내용을 추가합니다.
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <!-- Specify URL scheme to use when returning from LINE to your app. -->
      <string>line3rdp.$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    </array>
  </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
  <!-- Specify URL scheme to use when launching LINE from your app. -->
  <string>lineauth2</string>
</array>
ios/Podfile에 다음과 같은 내용을 추가한다.(원래 있는 경우엔 필요없다)
target 'Runner' do
  use_frameworks!               // 追記
  platform :ios, '10.0'   // 追記

안드로이드 설정

android/app/build.gradleminSdkVersion는 21(이상)로 설정했다.(원본이라면 가능)
defaultConfig {    
    minSdkVersion 21  // 21以上にする

main.데이터를 추서하다


iOS/(Android) 설정이 완료되면 main.dart에 추가LineSDK.instance.setup("チャンネルID");됩니다.
채널 ID방금 만든 채널의 ID(String)를 입력합니다.
이번 경우riverpod,firebase를 사용했기 때문에 내용은 다음과 같습니다.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_line_sdk/flutter_line_sdk.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'app/auth_manager/auth_manager.dart';
import 'app/home_page/home_page.dart';
import 'app/sign_in/sign_in_page.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(); // firebaseの初期化
  // ↓に先ほど作成したチャンネルのチャンネルIDを入れる(String)
  await LineSDK.instance.setup("チャンネルID"); 
  runApp(
    // riverpod用の記述
    const ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends ConsumerWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final _authManager = ref.watch(authManagerProvider);
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'タイトル',
      // ログイン中:ホーム画面、未ログイン:ログイン画面
      home: _authManager.isLoggedIn ? const HomePage() : const SignInPage(),
    );
  }
}
이렇게 하면 먼저 응용 프로그램 측면에서 LINE에 로그인할 수 있습니다.

Firebase 사용자 지정 토큰을 가져오는 함수 만들기


이로써 진행화상도할 수 있는①LINEログインして LINEのuser情報取得 상태가 됐다.
그런 다음 Cloud Function 함수를 생성하여 구현합니다②LINEから取得したuserIdを使用して Cloud FunctionsでFirebase用のカスタムトークンを作成.
Cloud Function의 개요, 사용 방법은 생략됩니다.

Firebase Admin SDK 준비


맞춤형 토큰을 만들려면 Admin SDK가 필요하므로 npm에 패키지를 설치합니다.
path/to/your_app/functions/
$ npm install firebase-admin
Admin SDK를 사용하면 서비스 계정의 키가 필요하기 때문에Firebase 컨트롤러의 항목에서 다운로드 키(json)를 설정하고 path/to/your_app/functions/에 설정합니다.

함수 생성 - 프로그램


Admin SDK가 준비되면 함수를 path/to/your_app/functions/src/index.ts에 씁니다.(이번에는 Type Script 사용)
Cloud Function의 트리거는 여러 가지가 있는데 이번에는 응용 프로그램에서 호출하기 위해서HTTP 요청.
import * as functions from "firebase-functions";
import * as admin from "firebase-admin";

// 先ほど配置したサービスアカウントのキーのパスを指定する
const serviceAccount = require("../xxxxx.json");

admin.initializeApp({
  credential: admin.credential.cert(serviceAccount)
});

exports.fetchCustomToken = functions
.region('asia-northeast1')
.https
.onRequest(async(request, response) => {
  const userId = request.body.data.userId;

  // userIdが不正の場合はエラーで終了
  if (typeof userId !== "string"){
    console.log("userId is not string");
    response.status(404).send({
      data: {"error": "userId is not string"},
    });
    return;
  }
  
  const customToken = await admin.auth().createCustomToken(userId);
  response.status(200).send({
    data: {"customToken": customToken},
  });
});
디버깅만 하면 OK.

설치 프로그램 측면의 로그인 처리


마침내 마지막 단계에 이르렀다.

cloud_functions 패키지 설치


응용 프로그램에서 Cloud Function을 호출하기 위해 패키지가 미리 설치되어 있습니다.
포장은 여기 있어요.

auth_manager.데이터의 최종 형식


일련의 준비가 다 되어 마침내 완성되었다auth_manager.dart.
코드는 다음과 같습니다.
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_line_sdk/flutter_line_sdk.dart';  // LINE SDK追加
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:cloud_functions/cloud_functions.dart'; // cloud_functions追加

final authManagerProvider = ChangeNotifierProvider<AuthManager>(
  (ref) {
    return AuthManager();
  },
);

class AuthManager with ChangeNotifier {
  AuthManager() {
    _firebaseAuth.authStateChanges().listen((user) {
      isLoggedIn = user != null;
      notifyListeners();
    });
  }
  final _firebaseAuth = FirebaseAuth.instance;
  final _lineSdk = LineSDK.instance;  // LINE SDKのインスタンス
  bool isLoggedIn = false;
   
  // ログイン処理
  Future<void> signInWithLine() async {
    // LINEログインし、LINEのuserIdを取得する
    final result = await _lineSdk.login();
    final lineUserId = result.userProfile?.userId;
    
    // LINEのuserIdを使って、Cloud Functionsからカスタムトークンを取得する
    final callable = FirebaseFunctions.instanceFor(region: 'asia-northeast1')
        .httpsCallable('fetchCustomToken');
    final response = await callable.call({
      'userId': lineUserId,
    });
    
    // functionsから取得したカスタムトークンを使用して、Firebaseログイン
    await _firebaseAuth.signInWithCustomToken(response.data['customToken']);
  }
  
  // ログアウト処理
  Future<void> signOut() async {
      // LINE, Firebase両方でログアウトする
    await _lineSdk.logout();
    await _firebaseAuth.signOut();
  }
}
잘못된 처리는 사랑을 끊는 것이니 양해해 주십시오
앞에서 설명한 바와 같이 LINE에 로그인한 다음 사용자 지정 토큰→Firebase 로그인을 가져옵니다.
또한 로그아웃과 관련해서는 LINE 및 Firebase가 모두 수행됩니다.

자 로그인!!


대체적으로 설치가 끝났기 때문에, 우선 안드로이드 구축으로 로그인을 시도해 봅시다.
나는 평소 아이폰을 사용하며 동작을 확인하기 위해 안드로이드로 라인에 로그인했다.
PC나 아이패드라면 스마트폰과 병행해서 사용할 수 있지만 여러 스마트폰 계정을 동시에 사용할 수는 없고, 안드로이드에 로그인할 때 아이폰의 라인 정보가 삭제돼 사용할 수 없기 때문에 주의가 필요하다.
미리 대화를 나누는 백업으로 아이폰으로 다시 로그인할 때 원래 상태로 돌아갈 수 있기 때문에 미리 백업하는 것을 추천한다.
안드로이드에서 오래 사용하면 중간 교환이 복원되지 않아 불완전한 복원이 발생할 수 있으니 주의하세요.
무사히 로그인 성공!!
Firebase 콘솔을 보면 user가 추가된 것을 알 수 있습니다.
그나저나 이것ユーザー UID은 라인에서 얻은 것이다userProfile.userId.

로그아웃→다시 로그인할 때 계정이 중복되지 않고 동일user로 순조롭게 로그인되었습니다.
이후 아이폰도 같은 라인 계정으로 로그인을 시도했으나 결과적으로 성공했다.

최후


긴 길이지만 Firebase Auth와 LINE SDK를 조합하여 LINE 로그인을 수행할 수 있습니다.
그러나 이 프로그램이 발표되기 전까지는 정식 환경에서 실행되는지 검증되지 않았다.
다른 설정이 필요할지도 모르니 알면 추가 예약할게요.
Firebase Auth의 사용자 정의 인증 이외의 (Clund Function을 사용하지 않아도 됨) 방법을 다시 검토하고 싶습니다.
LINE 로그인의 필요성을 다시 한번 검토해볼 수 있다는 보도도 있다.
https://qiita.com/pochi-sato/items/c1d51f310f5427253a3b

추기


Cloud Function을 사용하지 않는 방법도 적었습니다.
https://zenn.dev/yskuue/articles/7f0a93f9e17b50

참고 문장


https://techblog.yahoo.co.jp/advent-calendar-2018/firebase-flutter-yid/
https://firebase.google.com/docs/auth/admin/create-custom-tokens?hl=ja
https://firebase.flutter.dev/docs/functions/usage
https://csiandal.medium.com/firebase-cloud-function-error-response-is-not-valid-json-object-401221c3cb89

좋은 웹페이지 즐겨찾기