Giới thiệu
Rút ngắn quá trình đăng ký đăng nhập làm tăng trải nghiệm người dùng là xu thế chung của các ứng dụng hiện nay. Việc sử dụng các nền tảng SNS để xác thực trở nên phổ biến và được hỗ trợ nhiều từ phía các nền tảng như Facebook, Line, Twitter, Apple, …
Trong bài viết hôm nay, mình sẽ hướng dẫn các bước để thêm tính năng xác thực qua LINE trong project iOS
Cấu hình LINE
Bước 1: Truy cập Link developers.line.biz và đăng nhập bằng tài khoản LINE
Bạn có thể sử dụng tài khoản LINE cá nhân hoặc đăng ký tài khoản LINE Business cho ứng dụng của mình
Bước 2: Tạo một Provider
Provider có thể là một cá nhân, công ty hay tổ chức cung cấp dịch thông qua LINE platform. Ở đây mình sẽ tạo ra provider có tên là DemoLogin
Giao diện sau khi tạo và chọn Provider
Trong Provider có một vài Setting nhưng với ví dụ này chúng ta sẽ chưa cần quan tâm đến
Bước 3: Tạo và cấu hình cho Channel
Channel là kênh giao tiếp giữa các phương thức được cung cấp bởi LINE Platform và dịch vụ của Provider
Chọn “Create a LINE Login Channel”
Mình sẽ tạo ra một Channel có tên DemoLoginApp, lựa chọn App types là “Mobile App” và thêm description cho Channel (Bắt buộc)
Lưu ý khi tạo tên Channel không được bao gồm chữ “LINE”
Đây là giao diện sau khi tạo xong Channel
Ở đây các bạn cần để ý Channel ID. Lát chúng ta sẽ sử dụng để config cho App
Chuyển sang tab LINE Login và điền BundleID của App vào mục iOS bundle ID. BundleID của App các bạn có thể tìm trong mục General Setting của project trong XCode
Trường iOS universal link có thể bỏ trống vì là optional. LINE khuyến khích các bạn sử dụng Universal Link để tăng tính bảo mật khi giao tiếp giữa LINE và ứng dụng. Trong ví dụ này mình sẽ chỉ sử dụng bundle ID để kết nối với App
Cấu hình ứng dụng
Bước 1: Thêm LINE SDK vào trong Project. Mình sẽ sử dụng Cocoapods trong demo này
Ngoài ra LINE cũng hỗ trợ các phương thức khác để thêm SDK vào Project. Mọi người có thể tham khảo https://developers.line.biz/en/docs/ios-sdk/swift/setting-up-project/#installation
Bước 2: Mở file Info.plist dưới dạng Source Code và thêm đoạn mã này vào trước thẻ </dict> cuối cùng
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="token operator"><</span>key<span class="token operator">></span><span class="token builtin">CFBundleURLTypes</span><span class="token operator"><</span><span class="token operator">/</span>key<span class="token operator">></span> <span class="token operator"><</span>array<span class="token operator">></span> <span class="token operator"><</span>dict<span class="token operator">></span> <span class="token operator"><</span>key<span class="token operator">></span><span class="token builtin">CFBundleTypeRole</span><span class="token operator"><</span><span class="token operator">/</span>key<span class="token operator">></span> <span class="token operator"><</span>string<span class="token operator">></span><span class="token builtin">Editor</span><span class="token operator"><</span><span class="token operator">/</span>string<span class="token operator">></span> <span class="token operator"><</span>key<span class="token operator">></span><span class="token builtin">CFBundleURLSchemes</span><span class="token operator"><</span><span class="token operator">/</span>key<span class="token operator">></span> <span class="token operator"><</span>array<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token builtin">Specify</span> <span class="token constant">URL</span> scheme to use when returning from <span class="token constant">LINE</span> to your app<span class="token punctuation">.</span> <span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>string<span class="token operator">></span>line3rdp<span class="token punctuation">.</span>$<span class="token punctuation">(</span><span class="token constant">PRODUCT_BUNDLE_IDENTIFIER</span><span class="token punctuation">)</span><span class="token operator"><</span><span class="token operator">/</span>string<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>array<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>dict<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>array<span class="token operator">></span> <span class="token operator"><</span>key<span class="token operator">></span><span class="token builtin">LSApplicationQueriesSchemes</span><span class="token operator"><</span><span class="token operator">/</span>key<span class="token operator">></span> <span class="token operator"><</span>array<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span> <span class="token builtin">Specify</span> <span class="token constant">URL</span> scheme to use when launching <span class="token constant">LINE</span> from your app<span class="token punctuation">.</span> <span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>string<span class="token operator">></span>lineauth2<span class="token operator"><</span><span class="token operator">/</span>string<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>array<span class="token operator">></span> |
Bước 3: Cấu hình LINE SDK trong App Delegate và Scence Delegate
Ở bước này chúng ta sẽ sử dụng tới Channel ID mình đã nhắc ở trên
import LineSDK và thêm câu lệnh như trong hình để set up, thay “YOUR_CHANNEL_ID” bằng id của Channel nãy vừa tạo
LINE khuyến khích chúng ta sử dụng universal link để mở App sau khi hoàn thành Login. Cách này bảo mật hơn so với việc mở App trực tiếp từ Bundle ID được đăng kí. Cài đặt universal link cần server và domain cũng như setup tương đối phức tạp nên trong ví dụ này mình sẽ chưa sử dụng tới. Do đó trường universalLinkURL sẽ set nil
1 2 3 4 5 6 7 8 9 10 |
<span class="token atrule">@UIApplicationMain</span> <span class="token keyword">class</span> <span class="token class-name">AppDelegate</span><span class="token punctuation">:</span> <span class="token builtin">UIResponder</span><span class="token punctuation">,</span> <span class="token builtin">UIApplicationDelegate</span> <span class="token punctuation">{</span> <span class="token keyword">func</span> <span class="token function">application</span><span class="token punctuation">(</span><span class="token number">_</span> application<span class="token punctuation">:</span> <span class="token builtin">UIApplication</span><span class="token punctuation">,</span> didFinishLaunchingWithOptions launchOptions<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">UIApplication</span><span class="token punctuation">.</span><span class="token builtin">LaunchOptionsKey</span><span class="token punctuation">:</span> <span class="token builtin">Any</span><span class="token punctuation">]</span><span class="token operator">?</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">Bool</span> <span class="token punctuation">{</span> <span class="token builtin">LoginManager</span><span class="token punctuation">.</span>shared<span class="token punctuation">.</span><span class="token function">setup</span><span class="token punctuation">(</span>channelID<span class="token punctuation">:</span> <span class="token string">"YOUR_APP_ID"</span><span class="token punctuation">,</span> universalLinkURL<span class="token punctuation">:</span> <span class="token constant">nil</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Để xử lý response trả về từ LINE, chúng ta cẩn bổ sung thêm phương thức sau trong AppDelegate
1 2 3 4 |
<span class="token keyword">func</span> <span class="token function">application</span><span class="token punctuation">(</span><span class="token number">_</span> app<span class="token punctuation">:</span> <span class="token builtin">UIApplication</span><span class="token punctuation">,</span> open url<span class="token punctuation">:</span> <span class="token constant">URL</span><span class="token punctuation">,</span> options<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token builtin">UIApplication</span><span class="token punctuation">.</span><span class="token builtin">OpenURLOptionsKey</span> <span class="token punctuation">:</span> <span class="token builtin">Any</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">:</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token operator">-</span><span class="token operator">></span> <span class="token builtin">Bool</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token builtin">LoginManager</span><span class="token punctuation">.</span>shared<span class="token punctuation">.</span><span class="token function">application</span><span class="token punctuation">(</span>app<span class="token punctuation">,</span> open<span class="token punctuation">:</span> url<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Với iOS 13 trở lên, URL trả về sẽ được gọi bởi UISceneDelegate. Do đó ta cần thêm đoạn mã sau trong Scene Delegate
1 2 3 4 5 |
<span class="token comment">// SceneDelegate.swift</span> <span class="token keyword">func</span> <span class="token function">scene</span><span class="token punctuation">(</span><span class="token number">_</span> scene<span class="token punctuation">:</span> <span class="token builtin">UIScene</span><span class="token punctuation">,</span> openURLContexts <span class="token builtin">URLContexts</span><span class="token punctuation">:</span> <span class="token builtin">Set</span><span class="token operator"><</span><span class="token builtin">UIOpenURLContext</span><span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token number">_</span> <span class="token operator">=</span> <span class="token builtin">LoginManager</span><span class="token punctuation">.</span>shared<span class="token punctuation">.</span><span class="token function">application</span><span class="token punctuation">(</span><span class="token punctuation">.</span>shared<span class="token punctuation">,</span> open<span class="token punctuation">:</span> <span class="token builtin">URLContexts</span><span class="token punctuation">.</span><span class="token builtin">first</span><span class="token operator">?</span><span class="token punctuation">.</span>url<span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Bước 4: Tạo giao diện
Giao diện mình sẽ tạo một Button. Chúng ta có thể sử dụng sẵn đối tượng được cung cấp bởi LINE là LoginButton và implement LoginButtonDelegate cho controller để nhận được data reponse
Ngoài ra chúng ta có thể tạo button như bình thường và gọi hàm login bằng code
Bổ sung đoạn code sau
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span class="token atrule">@IBAction</span> <span class="token keyword">func</span> <span class="token function">loginWithLineAccount</span><span class="token punctuation">(</span><span class="token number">_</span> sender<span class="token punctuation">:</span> <span class="token builtin">Any</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token builtin">LoginManager</span><span class="token punctuation">.</span>shared<span class="token punctuation">.</span><span class="token function">login</span><span class="token punctuation">(</span>permissions<span class="token punctuation">:</span> <span class="token punctuation">[</span><span class="token punctuation">.</span>profile<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">in</span><span class="token punctuation">:</span> <span class="token keyword">self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> result <span class="token keyword">in</span> <span class="token keyword">switch</span> result <span class="token punctuation">{</span> <span class="token keyword">case</span> <span class="token punctuation">.</span><span class="token function">success</span><span class="token punctuation">(</span><span class="token keyword">let</span> loginResult<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span>loginResult<span class="token punctuation">.</span>accessToken<span class="token punctuation">.</span>value<span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token keyword">let</span> profile <span class="token operator">=</span> loginResult<span class="token punctuation">.</span>userProfile <span class="token punctuation">{</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"User ID: <span class="token interpolation"><span class="token delimiter variable">(</span>profile<span class="token punctuation">.</span>userID<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"User Display Name: <span class="token interpolation"><span class="token delimiter variable">(</span>profile<span class="token punctuation">.</span>displayName<span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span> <span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"User Icon: <span class="token interpolation"><span class="token delimiter variable">(</span><span class="token function">String</span><span class="token punctuation">(</span>describing<span class="token punctuation">:</span> profile<span class="token punctuation">.</span>pictureURL<span class="token punctuation">)</span><span class="token delimiter variable">)</span></span>"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">case</span> <span class="token punctuation">.</span><span class="token function">failure</span><span class="token punctuation">(</span><span class="token keyword">let</span> error<span class="token punctuation">)</span><span class="token punctuation">:</span> <span class="token function">print</span><span class="token punctuation">(</span>error<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Run Project và chúng ta sẽ thu được kết quả
Response trả về
Tham khảo
https://developers.line.biz/en/