OAuth2是一种授权框架,允许第三方应用在用户授权下访问用户在服务提供商上的资源,而无需共享用户的凭证。它通过颁发访问令牌来实现这一功能。
对于React Native应用,推荐使用授权码模式或PKCE扩展授权码模式(防止授权码拦截攻击)。
npm install axios react-native-keychain @react-native-async-storage/async-storage
import { authorize } from 'react-native-app-auth';
import axios from 'axios';
import * as Keychain from 'react-native-keychain';
// 配置OAuth2提供商
const config = {
issuer: 'https://your-auth-server.com',
clientId: 'YOUR_CLIENT_ID',
redirectUrl: 'com.your.app://oauthredirect',
scopes: ['openid', 'profile', 'email'],
serviceConfiguration: {
authorizationEndpoint: 'https://your-auth-server.com/oauth2/auth',
tokenEndpoint: 'https://your-auth-server.com/oauth2/token',
},
// 对于PKCE
usePKCE: true,
};
// 登录函数
const login = async () => {
try {
// 授权请求
const authState = await authorize(config);
// 存储令牌
await Keychain.setGenericPassword(
'authTokens',
JSON.stringify({
accessToken: authState.accessToken,
refreshToken: authState.refreshToken,
accessTokenExpirationDate: authState.accessTokenExpirationDate,
})
);
return authState;
} catch (error) {
console.error('Login failed:', error);
throw error;
}
};
// 创建axios实例
const apiClient = axios.create({
baseURL: 'https://your-api-server.com',
});
// 请求拦截器添加令牌
apiClient.interceptors.request.use(async (config) => {
const credentials = await Keychain.getGenericPassword();
if (credentials) {
const { accessToken } = JSON.parse(credentials.password);
config.headers.Authorization = `Bearer ${accessToken}`;
}
return config;
});
// 示例API调用
const fetchUserProfile = async () => {
try {
const response = await apiClient.get('/api/user/profile');
return response.data;
} catch (error) {
console.error('Failed to fetch profile:', error);
throw error;
}
};
apiClient.interceptors.response.use(
response => response,
async error => {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
try {
const credentials = await Keychain.getGenericPassword();
if (!credentials) throw new Error('No credentials found');
const { refreshToken } = JSON.parse(credentials.password);
const response = await axios.post(
`${config.issuer}/oauth2/token`,
{
grant_type: 'refresh_token',
refresh_token: refreshToken,
client_id: config.clientId,
}
);
// 存储新令牌
await Keychain.setGenericPassword(
'authTokens',
JSON.stringify({
accessToken: response.data.access_token,
refreshToken: response.data.refresh_token || refreshToken,
accessTokenExpirationDate: new Date(
Date.now() + response.data.expires_in * 1000
).toISOString(),
})
);
// 重试原始请求
originalRequest.headers.Authorization = `Bearer ${response.data.access_token}`;
return apiClient(originalRequest);
} catch (refreshError) {
console.error('Token refresh failed:', refreshError);
// 可能需要重新登录
throw refreshError;
}
}
return Promise.reject(error);
}
);
react-native-keychain
而不是AsyncStorage通过以上实现,你可以在React Native应用中安全地集成OAuth2认证并使用访问令牌调用受保护的REST API。
没有搜到相关的文章