使用OAuth 2.0构建React原生应用程序并进行身份验证
本文最初发表于Okta开发者博客必威滚.感谢您对合作伙伴的支持,是他们让SitePoint成为可能。必威西盟体育网页登录
使用Okta和OpenID Connect (OIDC),您可以轻松地将身份验证集成到React Native应用程序中,而无需再次自己构建。OIDC允许您直接根据Okta API,本文向您展示如何在React Native应用程序中做到这一点。今天你将看到如何通过AppAuth库使用OIDC重定向将用户登录到React Native应用程序。
React Native是一个非常灵活的框架。与Ionic和其他混合移动框架不同,它允许您使用web技术(React和JavaScript)来构建原生移动应用程序。它不涉及浏览器或WebView,所以使用React Native开发移动应用程序类似于使用原生SDK,因为你将在模拟器或设备上进行所有测试。没有办法像Ionic那样在浏览器中测试它。这可能是一个好处,因为你不必编写在浏览器和设备上分别工作的代码。
如果你看看谷歌Trends,你会发现React Native甚至比Android和iOS更受欢迎。
今天我将向你展示如何开发一个React Native应用程序,使用最新和最好的版本。在撰写本文时,这是React 16.2.0和React Native 0.54 4.0。您将创建一个新的应用程序,添加AppAuth要进行身份验证,请使用Okta进行身份验证,并看到它在iOS和Android上运行。
AppAuth是本地应用程序的客户端SDK,用于使用OAuth 2.0和OpenID Connect对最终用户进行身份验证和授权。适用于iOS, macOS, Android和原生JS环境,它实现了现代的安全性和可用性最佳实践用于本地应用程序的身份验证和授权。
创建React原生应用程序
React有一个create-react-app
命令行工具(CLI),您可以使用它来创建新的React应用程序。React Native有一个类似的工具叫做创建React原生应用.在安装之前,请确保已安装节点安装V6或更高版本。
安装create-react-native-app
并创建一个新项目okta-rn
:
npm安装-g create-react-native-app okta-rncdokta-rnnpm开始
运行这些命令会导致你的终端提示你一些选项:
要查看实时重新加载的应用程序,请将世博会应用程序指向此二维码。你会在应用程序的项目选项卡上找到二维码扫描仪。[二维码]或在应用程序的搜索栏中输入这个地址:exp://172.31.98.12:19000你的手机需要和这台电脑在同一个本地网络上。如需安装世博app的链接,请访问https://expo.io。服务应用程序的日志将出现在这里。随时按Ctrl+C停止。›按a打开Android设备或模拟器,按i打开iOS模拟器。›按q显示二维码›按“r”重启packager,按“r”重启packager并清空缓存。›按d切换开发模式。(当前模式:开发)
如果你用的是Mac,按一下我打开iOS模拟器。系统将提示您安装/打开Expo,然后呈现呈现的结果App.js
.
如果你使用的是Windows或Linux系统,我建议你试试Android模拟器或Android设备(如果你有的话)。如果它不起作用,不要担心,我稍后会向您展示如何使其工作。
提示:你可以在React Native应用中使用TypeScript而不是JavaScriptTypeScript React Native Starter.如果你决定走这条路,我建议你在完成本教程后按照以下步骤转换应用。
React Native和OAuth 2.0
在本例中,我将使用React原生应用程序认证创建的库强大的.我使用这个库的原因有三个方面:1)它们提供了优秀的例子我能够在短短几分钟内完成工作,2)它使用AppAuth(一个成熟的OAuth客户端实现),3)我无法让任何其他工作。
- 我试着react-native-oauth但是发现在添加新的提供者之前,它需要使用现有的提供者。我只想让奥克塔做我的供养者。此外,问题和拉请求的数量也很高,这是一个警告信号。
- 我试着react-native-simple-auth但在让已弃用的Navigator组件与最新的React Native版本一起工作时遇到了问题。
- 我试过这个OAuth 2与React Native教程,但重定向回我的应用程序也有问题。
在Okta中创建本机应用程序
在将AppAuth添加到React Native应用程序之前,您需要一个应用程序进行授权。如果你没有一个永远免费的Okta开发者帐户,今天就买一个!
登录您的Okta开发人员帐户并导航到应用程序>添加应用程序.点击本地的并点击下一个.给应用程序起一个你能记住的名字(例如,反应本地
),选择刷新令牌
作为一种授权类型,除了默认值授权代码
.复制登录重定向URI(例如,com.oktapreview.dev - 158606: /回调
)并保存在某个地方。在配置应用程序时需要这个值。
点击完成你应该在下一个屏幕上看到一个客户ID。复制并保存此值。
添加React Native AppAuth用于身份验证
你需要“弹出”应用程序的本机配置,这通常是由create-react-native-app隐藏的。
npm运行喷射
当提示回答问题时,请使用以下答案:
问题 | 回答 |
---|---|
你想如何从create-react-native-app中弹出? | 反应本地 |
你的应用应该在用户的主屏幕上显示什么? | Okta RN |
你的Android Studio和Xcode项目应该叫什么名字? | OktaRN |
为React Native安装App Auth,运行以下命令:
npm我react-native-app-auth@2.2.0npm我react-native链接
运行这些命令后,您必须配置本地iOS项目.为了方便起见,我复制了下面的步骤。
iOS设置
React Native App Auth依赖于AppAuth-ios,因此您必须将其配置为依赖项。最简单的方法就是用CocoaPods.使用实例安装CocoaPods。
sudo宝石安装cocoapods
创建一个Podfile
在ios
指定AppAuth-ios作为依赖项的项目目录。确保OktaRN
与运行时指定的应用程序名称匹配NPM运行弹出
.
平台:ios, '11.0'目标'OktaRN'做pod 'AppAuth', '>= 0.91'结束
然后运行圆荚体安装
从ios
目录中。第一次这样做可能需要一段时间,即使是在快速连接上。现在是喝杯咖啡或苏格兰威士忌的好时机!
通过运行在Xcode中打开你的项目打开OktaRN.xcworkspace
从ios
目录中。
如果你打算支持iOS 10及更老版本,你需要在中定义支持的重定向URL方案ios / OktaRN / Info.plist
如下:
<关键>CFBundleURLTypes关键><数组><dict><关键>CFBundleURLName关键><字符串>$ (PRODUCT_BUNDLE_IDENTIFIER)字符串><关键>CFBundleURLSchemes关键><数组><字符串>{yourReversedOktaDomain}字符串>数组>dict>数组>
下面是我更改应用程序标识符并添加此键后的情况。
CFBundleIdentifier com. okita .developer.reactnative.$(PRODUCT_NAME:rfc1034identifier) CFBundleURLTypes CFBundleURLName $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleURLSchemes com.oktapreview.dev-158606
开放AppDelegate.h
在你的Xcode项目(OktaRN > OktaRN >AppDelegate.h
),然后用+
就在下面。
+ @协议OIDAuthorizationFlowSession;@interface AppDelegate: UIResponder + @property(nonatomic, strong, nullable) id currentAuthorizationFlow;@property (nonatomic, strong) UIWindow *window;@end
此属性保存在重定向到Okta之前开始的授权流信息。在Okta授权你之后,它会重定向到redirect_uri
这是传入的。
授权流开始于openURL ()
应用程序委托方法。要添加它,打开AppDelegate.m
和导入AppAuth.h
.
#进口“AppAuth.h”
然后在课的最后(之前@end
),加上openURL ()
方法。
- (BOOL)应用程序:(UIApplication *)应用程序openURL:(NSURL *)url选项:(NSDictionary *)选项{if ([_currentAuthorizationFlow resumeAuthorizationFlowWithURL:url]) {_currentAuthorizationFlow = nil;返回YES;}返回NO;}
构建React原生应用程序
替换中的代码App.js
使用下面的JavaScript。这段代码允许您授权、刷新访问令牌和撤销它。
进口反应,{组件}从“反应”;进口{UIManager,LayoutAnimation}从“react-native”;进口{授权,刷新,撤销}从“react-native-app-auth”;进口{页面,按钮,ButtonContainer,形式,标题}从”。/组件的;UIManager.setLayoutAnimationEnabledExperimental& &UIManager.setLayoutAnimationEnabledExperimental(真正的);常量作用域=[openid的,“配置文件”,“电子邮件”,“offline_access”];类型状态={hasLoggedInOnce:布尔,accessToken:?字符串,accessTokenExpirationDate:?字符串,refreshToken:?字符串};常量配置={发行人:“https:// {yourOktaDomain} / oauth2 /违约”,clientId:“{clientId}”,redirectUrl:com。{yourReversedOktaDomain}: /回调的,additionalParameters:{},作用域:[openid的,“配置文件”,“电子邮件”,“offline_access”]};出口默认的类应用程序扩展组件<{},状态>{状态={hasLoggedInOnce:假,accessToken:”,accessTokenExpirationDate:”,refreshToken:”};animateState(nextState:美元的形状<状态>,延迟:数量=0){setTimeout(()= >{这.设置状态(()= >{LayoutAnimation.easeInEaseOut();返回nextState;});},延迟);}授权=异步()= >{试一试{常量authState=等待授权(配置);这.animateState({hasLoggedInOnce:真正的,accessToken:authState.accessToken,accessTokenExpirationDate:authState.accessTokenExpirationDate,refreshToken:authState.refreshToken},500);}抓(错误){警报.警报(“登录失败”,错误.消息);}};刷新=异步()= >{试一试{常量authState=等待刷新(配置,{refreshToken:这.状态.refreshToken});这.animateState({accessToken:authState.accessToken||这.状态.accessToken,accessTokenExpirationDate:authState.accessTokenExpirationDate||这.状态.accessTokenExpirationDate,refreshToken:authState.refreshToken||这.状态.refreshToken});}抓(错误){警报.警报(“刷新令牌失败”,错误.消息);}};撤销=异步()= >{试一试{等待撤销(配置,{tokenToRevoke:这.状态.accessToken,sendClientId:真正的});这.animateState({accessToken:”,accessTokenExpirationDate:”,refreshToken:”});}抓(错误){警报.警报(“撤销令牌失败”,错误.消息);}};渲染(){常量{状态}=这;返回(<页面>{!!状态.accessToken?(<形式><形式.标签>accessToken</形式.标签><形式.价值>{状态.accessToken}</形式.价值><形式.标签>accessTokenExpirationDate</形式.标签><形式.价值>{状态.accessTokenExpirationDate}</形式.价值><形式.标签>refreshToken</形式.标签><形式.价值>{状态.refreshToken}</形式.价值></形式>):(<标题>{状态.hasLoggedInOnce?“再见。”:“你好,陌生人。”}</标题>)}<ButtonContainer>{!状态.accessToken& &(<按钮onPress={这.授权}文本=“授权”颜色=“# 017 cc0”/>)}{!!状态.refreshToken& &<按钮onPress={这.刷新}文本=“刷新”颜色=“# 24 c2cb”/>}{!!状态.accessToken& &<按钮onPress={这.撤销}文本=“撤销”颜色=“# EF525B”/>}</ButtonContainer></页面>);}}
一定要调整配置
你的设置。
常量配置={发行人:“https:// {yourOktaDomain} / oauth2 /违约”,clientId:“{clientId}”,redirectUrl:com。{yourReversedOktaDomain}: /回调的,...};
改变index.js
使用OktaRN
作为应用程序的名称。
AppRegistry.registerComponent(“OktaRN”,()= >应用程序);
此代码使用styled-components,因此您需要将其作为依赖项安装。
注意:在运行下面的命令之前,请确保导航到项目的根目录。
npm我styled-components
然后复制组件
目录到你的项目根目录从可怕的例子。
svn出口https://github.com/FormidableLabs/react-native-app-auth/trunk/Example/components
控件中引用的背景图像Page.js
组件。
svn出口https://github.com/FormidableLabs/react-native-app-auth/trunk/Example/assets
在iOS模拟器上运行
运行应用程序NPM运行ios
.
你应该会看到屏幕上写着"你好,陌生人"点击授权,系统会提示你继续还是取消。
点击继续你应该会看到Okta签到表。输入您的凭证,您将被重定向回应用程序。
您可以单击刷新查看访问令牌的值和过期日期的更改。
提示:如果动画在iOS模拟器中缓慢发生,切换调试>缓慢的动画.
安卓系统设置
要配置原生Android项目,首先要升级它使用的Gradle版本。
cdAndroid ./gradlew包装器——gradle-version4.6
React Native App Auth for Android依赖于AppAuth-android,但您需要添加正确的Android支持库版本到您的项目。
将谷歌Maven库添加到您的android / build.gradle
并升级Android Tools依赖:
Buildscript {repositories {jcenter()谷歌()}dependencies {classpath 'com.android.tools.build:gradle:3.0.1'}}
升级appcompat
依赖在android / app / build.gradle
来25.3.1
来匹配AppAuth的期望。
依赖{编译"com.android.support:appcompat-v7:25.3.1"}
删除buildToolsVersion“23.0.1”
因为这已经没有必要了。
更新compileSdkVersion
:
android {compileSdkVersion 25}
添加appAuthRedirectScheme
财产的defaultConfig
在android / app / build.gradle
:
android {defaultConfig{…manifest占位符= [appAuthRedirectScheme: '{yourReversedOktaDomain}']}}
在做了这个改变之后,我的defaultConfig
如下所示。
defaultConfig {applicationId "com. com。oktarn" minSdkVersion 16 targetSdkVersion 22 versionCode 1 versionName "1.0" ndk { abiFilters "armeabi-v7a", "x86" } manifestPlaceholders = [ appAuthRedirectScheme: 'com.oktapreview.dev-158606' ] }
在Android上运行
要在Android模拟器上尝试它,请运行NPM运行android
.如果您没有插入手机或Android虚拟设备(AVD)运行,您将看到一个错误:
*出错的地方:任务':app:installDebug'执行失败。> com.android.builder.testing.api.DeviceException:没有连接设备!
要解决这个问题,打开Android Studio,选择开放现有项目,并选择安卓
目录。如果系统提示您更新任何内容,请批准。
要创建一个新的AVD,请导航到工具>安卓>AVD管理器.创建一个新的虚拟设备并单击播放。我选择了Pixel 2,你可以从下面的设置中看到。
运行NPM运行android
一次。您应该看到一个欢迎屏幕,并且能够成功授权。
提示:修复已弃用项目“:app”中的配置“compile”。请改用“实现”。
,改变编译
下依赖关系
来实现
.有关详情,请参阅为Gradle 3.0.0迁移到Android插件.
升级到React Native的最新版本
的react-native-git-upgrade工具是一个方便的方法来升级您的项目,以使用最新版本。安装并运行它。
npm我-g react-native-git-upgradenpm我
或者,你可以改变你的package.json
有:“react-native 0.54.2”
然后运行npm我
.
获取和查看ID令牌
如果您想在访问令牌之外获得一个ID令牌,请添加idToken
作为类型的属性状态
和状态
变量App.js
.
类型状态={...idToken:?字符串};出口默认的类应用程序扩展组件<{},状态>{...状态={...idToken:”};
然后更新授权()
方法来设置属性authState
.类中添加类似的逻辑refresh ()
而且撤销()
方法。
授权=异步()= >{试一试{常量authState=等待授权(配置);这.animateState({hasLoggedInOnce:真正的,accessToken:authState.accessToken,accessTokenExpirationDate:authState.accessTokenExpirationDate,refreshToken:authState.refreshToken,idToken:authState.idToken},500);}抓(错误){警报.警报(“登录失败”,错误.消息);}};
要查看ID令牌中的内容,请安装缓冲.
npm我缓冲
在顶部导入它App.js
.
进口{缓冲}从“缓冲”;
然后更改呈现()
方法来解码它。
渲染(){常量{状态}=这;如果(状态.idToken){常量jwtBody=状态.idToken.分裂(“。”)[1];常量base64=jwtBody.取代(“- - -”,“+”).取代(“_”,' / ');常量decodedJwt=缓冲.从(base64,“base64”);状态.idTokenJSON=JSON.解析(decodedJwt);}...
最后,添加一个<形式。标签>
而且<形式。值>
显示访问令牌的行之后。
<形式。标签>ID Token {JSON.stringify(state.idTokenJSON)}
运行NPM运行ios
(或NPM运行android
),在Okta授权后,您应该会在ID令牌中看到声明。下面是一个截图,证明它可以在iOS模拟器。
使用您的访问令牌调用API
现在您已经有了一个访问令牌,您可以用它做什么?你可以用它来调用okta保护的API授权
头!
我写了关于如何创建一个“好啤酒”API使用Spring Boot和React进行Bootiful开发.您可以使用该应用程序的后端来证明它是有效的。
从GitHub克隆项目,并检查okta
分支。
git克隆https://github.com/oktadeveloper/spring-boot-react-example.gitgit结帐okta
修改spring-boot-react-example /服务器/ src / main /资源/ application.properties
设置发行人
而且clientId
.
okta.oauth2。发行人=https://{yourOktaDomain}/oauth2/default okta.oauth2.clientId={clientId}
注意:你需要有Java 8安装此Spring Boot应用程序。
通过运行启动应用程序。/ mvnw
从服务器
目录中。
回到React Native客户端。在App.js
,添加啤酒
作为状态
.
状态={...啤酒:[]};
中设置为相同的值撤销()
方法。添加一个fetchGoodBeers ()
方法,该方法使用访问令牌调用后端。
fetchGoodBeers=异步()= >{如果(这.状态.啤酒.长度){//如果beers已被填充,则重置为id令牌这.animateState({啤酒:[]})}其他的{获取(“http://localhost: 8080 / good-beers”,{头:{“授权”:`持票人$ {这.状态.accessToken}`}}).然后(响应= >响应.json()).然后(数据= >{这.animateState({啤酒:数据})}).抓(错误= >控制台.错误(错误));}};
提示:为了在Android模拟器(以及真正的手机)中工作,您需要进行更改本地主机
到您的IP地址。
在< ButtonContainer >
在底部,添加一个“好啤酒”按钮,允许您调用API,以及再次按下它来查看ID令牌。
{! !状态。accessToken && <按钮onPress={此。fetchGoodBeers}文本={!这.状态。啤酒.长度呢?'好啤酒':'ID Token'} color="#008000" />}
修改显示ID令牌的行,以显示来自API的JSON。
< Form.Label > {state.beers。长度呢?'好啤酒':'ID Token'}<形式。值>{JSON.字符串如果y(state.beers.length ? state.beers : state.idTokenJSON)}
在iOS模拟器中,按Command + R重新加载所有内容,你应该会看到JSON,当你点击好啤酒按钮。你可以在Android中使用重载Command + M(在Mac,CTRL + m在其他操作系统上)。
注意:有一个react-native-app-auth中的开放问题关于撤销不与Okta工作,因为一个授权
报头未发送。
了解更多关于React Native和React的信息
我希望你喜欢这个如何使用Okta和React Native进行身份验证的旋风之旅。你可以在上面了解更多关于React Native的信息官方网站.你也可以添加到它的~60K颗恒星GitHub上.
您可以在这里找到这个应用程序的源代码https://github.com/oktadeveloper/okta-react-native-app-auth-example.
如果你对如何使用Okta进行常规React开发感兴趣,我鼓励你查看以下资源:
如果你对这篇文章有任何问题,请在Twitter上联系我@mraible.