React Native — это платформа мобильных приложений с открытым исходным кодом для разработки собственных приложений для Android и iOS. Компоненты React преобразуются в собственные компоненты платформы, в отличие от использования JavaScript / HTML и веб-представления. React Native готов к использованию в ваших текущих приложениях для iOS и Android.
В этом руководстве я покажу вам, как использовать React Native с Okta для реализации функции входа в приложение в течение десяти минут. Для авторизации мы будем использовать OAuth 2.0, а для аутентификации мы будем использовать OpenID Connect. Аутентификация позволяет нам проверять, кто пользователь, а авторизация дает пользователю доступ к тому, что ему разрешено делать. Okta делает реализацию аутентификации очень простой и, тем более, React Native и React Native SDK от Okta .
React Native 0.61 был выпущен пару недель назад. Одна из его самых больших функций — Fast Refresh — объединение оперативной перезагрузки (перезагрузка при сохранении) и горячей перезагрузки. Fast Refreshful поддерживает функциональные компоненты современного React и перехватывает и восстанавливает после опечаток и других ошибок. В предыдущих версиях React Native распространенная жалоба заключалась в том, что «горячая перезагрузка» была нарушена.
Предпосылки:
- Узел 10
- Пряжа.
- Сторож.
- Java 8 (для Android).
- Okta аккаунт разработчика .
Чтобы установить эти предварительные условия в подсистеме Mac, Linux или Windows для Linux (WSL), я рекомендую использовать Homebrew .
Простой текст
1
brew install node
2
brew install yarn
3
brew install watchman
4
brew tap AdoptOpenJDK/openjdk
5
brew cask install adoptopenjdk8
Если вы не используете WSL для Windows, вы можете использовать Chocolatey для установки всего из командной строки:
Оболочка
xxxxxxxxxx
1
choco install -y nodejs.install python2 jdk8
Вам также необходимо загрузить и установить интегрированные среды разработки для Android и iOS:
- Android Studio (для Android).
- Xcode (для iOS).
Если вы предпочитаете смотреть видео, я создал скринкаст этого урока .
Создать React Native Application
Интерфейс командной строки React Native — это популярный способ начать разработку React Native.
Оболочка
xxxxxxxxxx
1
npm install -g react-native-cli@2.0.1
После установки React Native CLI вы можете создать новое приложение с помощью init
команды.
Оболочка
xxxxxxxxxx
1
react-native init ReactNativeLogin
Добавить логин с помощью OIDC
Okta предоставляет React Native SDK, который удобно оборачивает родные библиотеки Okta для Android OIDC и iOS OIDC .
Я собираюсь показать вам два способа добавления входа в систему на основе OIDC с помощью Okta: быстрый путь с помощью созданного мной инструмента и пошаговые инструкции.
Этот инструмент основан на Schematics и управляет вашим проектом для установки и настройки всего.
Установите Schematics глобально.
Оболочка
xxxxxxxxxx
1
npm install -g @angular-devkit/schematics-cli@0.803.7
Создать родное приложение в Okta
Войдите в свою учетную запись Okta Developer (или зарегистрируйтесь, если у вас нет учетной записи).
- На странице « Приложения» выберите « Добавить приложение» .
- На странице «Создание нового приложения» выберите Native в качестве платформы и нажмите « Далее» .
- Дайте вашему приложению запоминающееся имя, выберите
Refresh Token
тип гранта и нажмите « Готово» . - Нажмите кнопку « Изменить» и добавьте URI перенаправления выхода из системы, который соответствует стандартному URI перенаправления входа (например,
com.okta.dev-123456:/callback
). - Нажмите Сохранить .
Установить React Native OIDC Войти
В терминале перейдите в свой ReactNativeLogin
каталог и установите OktaDev Schematics:
Оболочка
xxxxxxxxxx
1
npm i @oktadev/schematics@1.0.0
Примечание . Если у вас есть приложение React Native 0.60.x, используйте @oktadev/schematics@0.9.0
. Единственная разница между ними — это тесты .
Запустите add-auth
схему в вашем ReactNativeLogin
проекте.
Оболочка
xxxxxxxxxx
1
schematics @oktadev/schematics:add-auth
Вам будет предложено для issuer
и clientId
. Вы можете найти своего эмитента в разделе API > Серверы авторизации на Okta.
Идентификатор клиента будет на экране вашего приложения.
Этот процесс займет минуту, чтобы завершить.
Настройте свой iOS-проект для использования Swift
React Native использует Objective-C, а библиотека Okta React Native использует Swift. Из-за этого вам нужно добавить файл Swift в ваш проект iOS для его компиляции. Выполните следующую команду, чтобы открыть свой родной проект iOS в XCode.
Оболочка
xxxxxxxxxx
1
open ios/ReactNativeLogin.xcworkspace
Чтобы добавить файл Swift, выполните следующие действия:
- Щелкните правой кнопкой мыши по вашему проекту и выберите « Новый файл…» .
- Выберите
Swift File
и нажмите Далее . - Введите имя (например,
Polyfill
) и нажмите « Создать» . - Если запрашивается файл заголовка, его не нужно создавать.
Затем перейдите ReactNativeLogin/ios
и запустите pod install
.
Совет : Если у вас не установлен CocoaPoads, вы можете установить его с помощью gem install cocoapods
.
Запустите свое собственное приложение React на iOS
Вернитесь в корневой каталог вашего приложения. Запустите ваше приложение, и вы сможете пройти аутентификацию с помощью Okta.
Простой текст
xxxxxxxxxx
1
react-native run-ios
После того, как вы войдете в систему, вы увидите варианты выхода из системы, получения информации о пользователе из ID-токена и получения информации о пользователе из getUser()
метода React Native SDK
(он же запрос).
Примечание : подсказку, когда вы нажимаете Войти, нельзя избежать. Это механизм безопасности iOS. Он также появляется при выходе из системы. Смотрите эту проблему для получения дополнительной информации.
Запустите приложение React Native на Android
Схема, которую вы запустили, изменяет все необходимые файлы для Android; никаких изменений кода не требуется!
Вам нужно будет запустить AVD (Android Virtual Device) перед запуском приложения, или вы можете подключить свой телефон Android и использовать его. Если у вас нет ни одной, запустите Android Studio и перейдите в Инструменты > AVD Manager . Нажмите « Создать виртуальное устройство» внизу и выберите нужный телефон. Я выбрал Pixel 3 XL с Android 10.
Запустите AVD, затем свое приложение и выполните аутентификацию с помощью Okta.
Простой текст
xxxxxxxxxx
1
react-native run-android
Нажмите кнопку « Получить идентификатор пользователя» , чтобы подтвердить, что вы можете получить информацию о пользователе.
Запустите установленные тесты React Native Authentication
В дополнение к интеграции входа в систему OktaDev Schematics также установила несколько тестов, которые проверяют работу входа в систему и аутентификации. Запустите, npm test
чтобы увидеть эти тесты в вашем терминале.
Простой текст
xxxxxxxxxx
1
Snapshot Summary
2
› 1 snapshot written from 1 test suite.
3
Test Suites: 2 passed, 2 total
5
Tests: 12 passed, 12 total
6
Snapshots: 1 written, 1 total
7
Time: 8.952s
8
Ran all test suites.
Примечание . OktaDev Schematics помещает тесты в tests
каталог, а не в __tests__
каталог по умолчанию, поскольку в Angular Schematics в качестве заполнителя используется двойное подчеркивание.
Использование пользовательского экрана входа в систему с Okta
В этом примере показано, как добавить поток OIDC, который открывает браузер, когда пользователь входит в систему и выходит из нее. Если вам требуется более плавный вход в систему, при котором браузер не открывается, см. Пример пользовательского входа Okta , например, код, показывающий, как реализовать этот тип потока.
Добавить OIDC Войти трудный путь
В предыдущем разделе показано, как использовать схему OktaDev для быстрого добавления функции входа (и тестирования!) В приложение React Native. Однако у вас может быть существующее приложение React Native, которое не имеет такой же структуры, как совершенно новое приложение React Native.
В этом разделе подробно рассказывается обо всем, что OktaDev Schematics делает для вас.
Создайте проект с помощью React Native CLI и установите SDK от Okta.
Оболочка
xxxxxxxxxx
1
react-native init ReactNativeLogin
2
cd ReactNativeLogin
3
npm install @okta/okta-react-native@1.2.1
Для iOS измените его, ios/Podfile
чтобы изменить его с iOS 9 на iOS 11.
Оболочка
xxxxxxxxxx
1
platform :ios, '11.0'
Откройте свой проект в Xcode.
Оболочка
xxxxxxxxxx
1
open ios/ReactNativeLogin.xcworkspace
Добавьте файл Swift.
- Щелкните правой кнопкой мыши по вашему проекту и выберите « Новый файл…» .
- Выберите
Swift File
и нажмите Далее . - Введите имя (например,
Polyfill
) и нажмите « Создать» . - Если запрашивается файл заголовка, его не нужно создавать.
Установите собственные зависимости iOS с CocoaPods.
Оболочка
xxxxxxxxxx
1
cd ios
2
pod install
Добавьте Jest и Enzyme, чтобы проверить свой React Native Login
Jest - это библиотека для тестирования приложений JavaScript, а Enzyme - это библиотека, которая облегчает выбор и запрос элементов в тестах. Они часто используются рядом друг с другом.
Установите тестирование зависимостей с помощью npm.
Оболочка
xxxxxxxxxx
1
npm i enzyme@3.10.0 enzyme-adapter-react-16@1.14.0 enzyme-async-helpers@0.9.1 react-dom@16.9.0
Затем измените свой jest
ключ в package.json
соответствии со следующим:
JSON
xxxxxxxxxx
1
"jest": {
2
"preset": "react-native",
3
"automock": false,
4
"transformIgnorePatterns": [
5
"node_modules/(?!@okta|react-native)"
6
],
7
"setupFiles": [
8
"./setupJest.js"
9
]
10
}
Создать, setupJest.js
чтобы заполнить React Native для Okta.
JavaScript
xxxxxxxxxx
1
// Required to correctly polyfill React-Native
2
import { configure } from 'enzyme';
4
import Adapter from 'enzyme-adapter-react-16';
5
import { NativeModules } from 'react-native';
6
configure({ adapter: new Adapter() });
8
global.XMLHttpRequest = jest.fn();
10
global.fetch = jest.fn();
11
if (typeof window !== 'object') {
13
global.window = global;
14
global.window.navigator = {};
15
}
16
NativeModules.OktaSdkBridge = {
18
createConfig: jest.fn(),
19
signIn: jest.fn(),
20
signOut: jest.fn(),
21
getAccessToken: jest.fn(),
22
getIdToken: jest.fn(),
23
getUser: jest.fn(),
24
isAuthenticated: jest.fn(),
25
revokeAccessToken: jest.fn(),
26
revokeIdToken: jest.fn(),
27
revokeRefreshToken: jest.fn(),
28
introspectAccessToken: jest.fn(),
29
introspectIdToken: jest.fn(),
30
introspectRefreshToken: jest.fn(),
31
refreshTokens: jest.fn(),
32
};
Создать Auth.js
для обработки вашего кода аутентификации.
Джава
xxxxxxxxxx
1
import React, { Component, Fragment } from 'react';
2
import { SafeAreaView, ScrollView, Button, StyleSheet, Text, View } from 'react-native';
4
import { createConfig, signIn, signOut, isAuthenticated, getUser, getUserFromIdToken, EventEmitter } from '@okta/okta-react-native';
5
import configFile from './auth.config';
6
export default class Auth extends Component {
8
constructor() {
9
super();
10
this.state = {
11
authenticated: false,
12
context: null,
13
};
14
this.checkAuthentication = this.checkAuthentication.bind(this);
15
}
16
async componentDidMount() {
18
let that = this;
19
EventEmitter.addListener('signInSuccess', function (e: Event) {
20
that.setState({authenticated: true});
21
that.setContext('Logged in!');
22
});
23
EventEmitter.addListener('signOutSuccess', function (e: Event) {
24
that.setState({authenticated: false});
25
that.setContext('Logged out!');
26
});
27
EventEmitter.addListener('onError', function (e: Event) {
28
console.warn(e);
29
that.setContext(e.error_message);
30
});
31
EventEmitter.addListener('onCancelled', function (e: Event) {
32
console.warn(e);
33
});
34
await createConfig({
35
clientId: configFile.oidc.clientId,
36
redirectUri: configFile.oidc.redirectUri,
37
endSessionRedirectUri: configFile.oidc.endSessionRedirectUri,
38
discoveryUri: configFile.oidc.discoveryUri,
39
scopes: configFile.oidc.scopes,
40
requireHardwareBackedKeyStore: configFile.oidc.requireHardwareBackedKeyStore,
41
});
42
this.checkAuthentication();
43
}
44
componentWillUnmount() {
46
EventEmitter.removeAllListeners('signInSuccess');
47
EventEmitter.removeAllListeners('signOutSuccess');
48
EventEmitter.removeAllListeners('onError');
49
EventEmitter.removeAllListeners('onCancelled');
50
}
51
async componentDidUpdate() {
53
this.checkAuthentication();
54
}
55
async checkAuthentication() {
57
const result = await isAuthenticated();
58
if (result.authenticated !== this.state.authenticated) {
59
this.setState({authenticated: result.authenticated});
60
}
61
}
62
async login() {
64
signIn();
65
}
66
async logout() {
68
signOut();
69
}
70
async getUserIdToken() {
72
let user = await getUserFromIdToken();
73
this.setContext(JSON.stringify(user, null, 2));
74
}
75
async getMyUser() {
77
let user = await getUser();
78
this.setContext(JSON.stringify(user, null, 2));
79
}
80
setContext = message => {
82
this.setState({
83
context: message,
84
});
85
};
86
renderButtons() {
88
if (this.state.authenticated) {
89
return (
90
<View style={styles.buttonContainer}>
91
<View style={styles.button}>
92
<Button
93
onPress={async () => {
94
this.getUserIdToken();
95
}}
96
title="Get User From Id Token"
97
/>
98
</View>
99
</View>
100
);
101
}
102
}
103
render() {
105
return (
106
<Fragment>
107
<SafeAreaView style={styles.container}>
108
<View style={styles.buttonContainer}>
109
<View style={styles.button}>
110
{this.state.authenticated ? (
111
<Button
112
style={styles.button}
113
testID="logoutButton"
114
onPress={async () => { this.logout() }}
115
title="Logout"
116
/>
117
) : (
118
<Button
119
style={styles.button}
120
testID="loginButton"
121
onPress={async () => { this.login() }}
122
title="Login"
123
/>
124
)}
125
</View>
126
</View>
127
{this.renderButtons()}
128
<ScrollView
129
contentInsetAdjustmentBehavior="automatic"
130
style={styles.context}>
131
<Text>{this.state.context}</Text>
132
</ScrollView>
133
</SafeAreaView>
134
</Fragment>
135
);
136
}
137
}
138
const styles = StyleSheet.create({
140
buttonContainer: {
141
flexDirection: 'column',
142
justifyContent: 'space-between',
143
},
144
button: {
145
width: 300,
146
height: 40,
147
marginTop: 10,
148
},
149
container: {
150
flex: 1,
151
flexDirection: 'column',
152
alignItems: 'center',
153
}
154
});
Вы можете заметить, что он импортирует файл конфигурации вверху.
JavaScript
xxxxxxxxxx
1
import configFile from './auth.config';
Создавайте auth.config
с вашими настройками OIDC от Okta.
JSON
xxxxxxxxxx
1
export default {
2
oidc: {
3
clientId: '$yourClientId',
4
redirectUri: 'com.okta.dev-#######:/callback',
5
endSessionRedirectUri: 'com.okta.dev-#######:/callback',
6
discoveryUri: 'https://dev-#######.okta.com/oauth2/default',
7
scopes: ['openid', 'profile', 'offline_access'],
8
requireHardwareBackedKeyStore: false,
9
},
10
};
Создайте приложение на Okta, чтобы получить значения для $yourClientId
и ######
.
- На странице « Приложения» выберите « Добавить приложение» .
- На странице «Создание нового приложения» выберите Native в качестве платформы и нажмите « Далее» .
- Дайте вашему приложению запоминающееся имя, выберите
Refresh Token
тип гранта и нажмите « Готово» . - Нажмите кнопку « Изменить» и добавьте URI перенаправления выхода из системы, который соответствует стандартному URI перенаправления входа (например,
com.okta.dev-123456:/callback
). - Нажмите Сохранить .
В App.js
, импорт Auth
.
JavaScript
xxxxxxxxxx
1
import Auth from './Auth';
Используйте его по-новому <View />
после логики Гермеса.
Джава
xxxxxxxxxx
1
<ScrollView
3
contentInsetAdjustmentBehavior="automatic"
4
style={styles.scrollView}>
5
<Header />
6
{global.HermesInternal == null ? null : (
7
<View style={styles.engine}>
8
<Text style={styles.footer}>Engine: Hermes</Text>
9
</View>
10
)}
11
<View style={styles.body}>
12
<View style={styles.sectionContainer}>
13
<Text style={styles.sectionTitle}>Step Zero</Text>
14
<Text style={styles.sectionDescription}>
15
Use <Text style={styles.highlight}>Okta</Text> for
16
authentication.
17
</Text>
18
<Auth />
19
</View>
На данный момент, ваши тесты не пройдут , потому что Okta использует EventEmitter для обмена данных между компонентами.
Добавить React Native Authentication Tests
Чтобы смоделировать собственный источник событий, который использует Okta, добавьте в него макет __tests__/App-test.js
.
Джава
xxxxxxxxxx
1
/**
2
* @format
3
*/
4
import 'react-native';
6
import React from 'react';
7
import renderer from 'react-test-renderer';
8
import App from '../App';
9
jest.mock(
11
'../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter',
12
);
13
it('renders correctly', () => {
15
renderer.create(<App />);
16
});
Чтобы убедиться, что логика входа и аутентификации работает, создайте __tests__/Auth-test.js
.
Джава
xxxxxxxxxx
1
import React from 'react';
2
import Auth from '../Auth';
3
import { shallow } from 'enzyme';
4
import renderer from 'react-test-renderer';
5
import { waitForState } from 'enzyme-async-helpers';
6
import { NativeEventEmitter } from 'react-native';
7
const nativeEmitter = new NativeEventEmitter();
9
jest
11
.mock(
12
'../node_modules/react-native/Libraries/Components/StatusBar/StatusBar',
13
() => 'StatusBar',
14
)
15
.mock(
16
'../node_modules/react-native/Libraries/Components/ScrollView/ScrollView',
17
() => 'ScrollView',
18
)
19
.mock(
20
'../node_modules/react-native/Libraries/EventEmitter/NativeEventEmitter',
21
);
22
global.fetch = jest
24
.fn()
25
.mockImplementation(() => {
26
return new Promise((resolve, reject) => {
27
resolve({
28
json: () => {
29
return {
30
user: [{ foo: 'foo', bar: 'bar' }],
31
}
32
},
33
ok: true,
34
});
35
});
36
})
37
.mockImplementationOnce(() => {
38
return new Promise((resolve, reject) => {
39
resolve({
40
json: () => {
41
return {
42
userinfo_endpoint: 'dummy_endpoint',
43
}
44
},
45
ok: true,
46
});
47
});
48
});
49
describe('auth setup', () => {
51
it('should render without crashing', () => {
52
const rendered = renderer.create(<Auth />).toJSON();
53
expect(rendered).toBeTruthy();
54
});
55
it('should render correctly', () => {
57
const rendered = renderer.create(<Auth />).toJSON();
58
expect(rendered).toMatchSnapshot();
59
});
60
it('should initialize with default state', () => {
62
const wrapper = shallow(<Auth />);
63
expect(wrapper.state().authenticated).toBe(false);
64
expect(wrapper.state().context).toBe(null);
65
});
66
it('should render login button if not authenticated', () => {
68
const wrapper = shallow(<Auth />);
69
const loginButton = wrapper.find('Button').get(0);
70
expect(loginButton.props.title).toBe('Login');
71
});
72
it('should render logout and get user info buttons if authenticated', () => {
74
const wrapper = shallow(<Auth />);
75
wrapper.setState({authenticated: true});
76
const logoutButton = wrapper.find('Button').get(0);
77
const getUserFromIdButton = wrapper.find('Button').get(1);
78
const getUserButton = wrapper.find('Button').get(2);
79
expect(logoutButton.props.title).toBe('Logout');
80
expect(getUserFromIdButton.props.title).toBe('Get User From Id Token');
81
expect(getUserButton.props.title).toBe('Get User From Request');
82
});
83
it('should not render login button if authenticated', () => {
85
const wrapper = shallow(<Auth />);
86
wrapper.setState({authenticated: true});
87
const loginButton = wrapper.find('Button').get(0);
88
expect(loginButton.props.title).not.toBe('Login');
89
});
90
it('should not render logout and get user info buttons if not authenticated', () => {
92
const wrapper = shallow(<Auth />);
93
const logoutButton = wrapper.find('Button').get(0);
94
const getUserFromIdButton = wrapper.find('Button').get(1);
95
const getUserButton = wrapper.find('Button').get(2);
96
expect(logoutButton.props.title).not.toBe('Logout');
97
expect(getUserFromIdButton).toBe(undefined);
98
expect(getUserButton).toBe(undefined);
99
});
100
});
101
describe('authentication flow', () => {
103
it('should detect when the user has logged in', async () => {
104
const wrapper = shallow(<Auth />);
105
const loginButton = wrapper.find('Button').get(0);
106
await loginButton.props.onPress();
107
expect(loginButton.props.title).toBe('Login');
108
nativeEmitter.emit('signInSuccess');
109
expect(wrapper.state().authenticated).toBe(true);
110
expect(wrapper.state().context).toBe('Logged in!');
111
});
112
it('should detect when the user has signed out', async () => {
114
const wrapper = shallow(<Auth />);
115
wrapper.setState({authenticated: true});
116
const logoutButton = wrapper.find('Button').get(0);
117
await logoutButton.props.onPress();
118
expect(logoutButton.props.title).toBe('Logout');
119
nativeEmitter.emit('signOutSuccess');
120
expect(wrapper.state().authenticated).toBe(false);
121
expect(wrapper.state().context).toBe('Logged out!');
122
});
123
it('should return user profile information from id token' , async () => {
125
const mockGetIdToken = require('react-native').NativeModules.OktaSdkBridge.getIdToken;
126
mockGetIdToken.mockImplementationOnce(() => {
127
// id_token returns { a: 'b' }
128
return {'id_token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhIjoiYiJ9.jiMyrsmD8AoHWeQgmxZ5yq8z0lXS67_QGs52AzC8Ru8'};
129
});
130
const wrapper = shallow(<Auth />);
131
wrapper.setState({authenticated: true});
132
const profileButton = wrapper.find('Button').get(1);
133
await profileButton.props.onPress();
134
await waitForState(wrapper, state => state.context !== null);
135
expect(profileButton.props.title).toBe('Get User From Id Token');
136
expect(wrapper.state().context).toContain('"a": "b"');
137
});
138
});
Беги, npm test
чтобы насладиться плодами своего труда!
Чтобы запустить приложение на iOS, используйте react-native run-ios
.
Чтобы запустить его на Android, вам нужно изменить файлы сборки Gradle.
React Native SDK от Okta зависит от библиотеки Android OIDC Okta . Вы должны добавить эту библиотеку через Gradle.
- Добавьте репо BinTray от Okta
android/build.gradle
, подallprojects
->repositories
.
Groovy
xxxxxxxxxx
1
1
maven {
2
url "https://dl.bintray.com/okta/com.okta.android"
3
}
- Убедитесь , что ваш
minSdkVersion
IS19
вandroid/build.gradle
. - Определите схему перенаправления для захвата перенаправления авторизации. В
android/app/build.gradle
, подandroid
->defaultConfig
, добавьте:manifestPlaceholders = [ appAuthRedirectScheme: 'com.okta.dev-###### ]
Наконец, запустите виртуальное устройство (или подключите телефон) и запустите react-native run-android
.
Узнайте больше о React Native и OIDC Login
В этом руководстве показано, как добавить функцию входа в приложение React Native. Вы узнали, что OAuth 2.0 - это протокол авторизации, а OIDC - это слой аутентификации поверх него. В своей реализации вы также использовали PKCE (Обмен ключами с открытым ключом), который является более безопасным способом реализации OAuth 2.0 в мобильных приложениях.
Надеюсь, вам понравится ваш путь разработки React Native и его функция быстрого обновления!
Вы можете найти исходный код для этого примера на GitHub по адресу oktadeveloper / okta-реагировать-native-login-example .
Чтобы узнать больше о React Native, OIDC и PKCE, ознакомьтесь со следующими статьями:
- Создайте приложение для iOS с React Native и опубликуйте его в App Store
- Дизайн и разработка приложения для Android с React Native и публикация в Google Play Store
- Идентификационные данные, утверждения и токены - учебник по OpenID Connect, часть 1 из 3
- Реализация кода авторизации OAuth 2.0 с помощью потока PKCE
- Почему ключи и секреты OAuth API небезопасны в мобильных приложениях
Если вам понравился этот урок, следите за @oktadev в Твиттере и подпишитесь на наш канал на YouTube .
Создание собственного приложения React с входом в систему за 10 минут было первоначально опубликовано в блоге разработчиков Okta 14 ноября 2019 года.