You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native应用中无提示刷新Apple登录并更新Azure App Service登录

无提示刷新Apple登录令牌(Expo + Azure App Service)

核心问题分析

你当前的困境源于两个关键误区:

  • 未正确获取并使用Apple登录返回的refreshToken
  • 调用Azure App Service的/.auth/refresh时使用了错误的凭证(用了id_token或access_token而非Azure返回的refresh_token)

正确实现步骤

1. 首次登录时完整保存凭证信息

调用AppleAuthentication.signInAsync成功后,除了identityToken,还要保存refreshToken(Apple提供的刷新令牌),以及Azure App Service登录接口返回的refresh_token(注意区分Apple的refreshToken和Azure的refresh_token)。

修改登录代码,确保保存所有必要凭证:

const credential = await AppleAuthentication.signInAsync({
  requestedScopes: [
    AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
    AppleAuthentication.AppleAuthenticationScope.EMAIL,
  ],
});

// 保存Apple的refreshToken到本地安全存储(推荐用expo-secure-store替代AsyncStorage)
await SecureStore.setItemAsync('appleRefreshToken', credential.refreshToken);

// 调用Azure登录接口
const azureLoginResponse = await fetch('https://myapi.azurewebsites.net/.auth/login/apple', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ id_token: credential.identityToken }),
});

const azureAuthData = await azureLoginResponse.json();
// 保存Azure返回的access_token和refresh_token
await SecureStore.setItemAsync('azureAccessToken', azureAuthData.access_token);
await SecureStore.setItemAsync('azureRefreshToken', azureAuthData.refresh_token);

2. 无提示刷新Apple令牌(解决Expo refreshAsync问题)

AppleAuthentication.refreshAsync需要传入有效的refreshToken,iOS平台下只要用户未取消App授权,就能无提示完成刷新。你之前返回无效结果大概率是未正确传入refreshToken。

正确调用方式:

const savedAppleRefreshToken = await SecureStore.getItemAsync('appleRefreshToken');
if (!savedAppleRefreshToken) {
  // 无刷新令牌,引导用户重新登录
  return;
}

try {
  const newCredential = await AppleAuthentication.refreshAsync({
    refreshToken: savedAppleRefreshToken,
  });
  // 更新本地存储的Apple凭证
  await SecureStore.setItemAsync('appleIdentityToken', newCredential.identityToken);
  // 若返回新的refreshToken则更新,否则保留原token
  if (newCredential.refreshToken) {
    await SecureStore.setItemAsync('appleRefreshToken', newCredential.refreshToken);
  }
} catch (error) {
  // 刷新失败(比如用户取消授权),引导重新登录
  console.error('Apple token refresh failed:', error);
}

3. 正确调用Azure App Service的令牌刷新接口

Azure的/.auth/refresh接口必须使用Azure返回的refresh_token,且需用POST请求:

const savedAzureRefreshToken = await SecureStore.getItemAsync('azureRefreshToken');
if (!savedAzureRefreshToken) {
  return;
}

try {
  const refreshResponse = await fetch('https://myapi.azurewebsites.net/.auth/refresh', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ refresh_token: savedAzureRefreshToken }),
  });

  if (refreshResponse.ok) {
    const newAzureAuthData = await refreshResponse.json();
    // 更新本地存储的Azure凭证
    await SecureStore.setItemAsync('azureAccessToken', newAzureAuthData.access_token);
    if (newAzureAuthData.refresh_token) {
      await SecureStore.setItemAsync('azureRefreshToken', newAzureAuthData.refresh_token);
    }
  } else {
    // Azure刷新失败,尝试用最新的Apple identityToken重新登录Azure
    const newAppleIdentityToken = await SecureStore.getItemAsync('appleIdentityToken');
    if (newAppleIdentityToken) {
      const reLoginResponse = await fetch('https://myapi.azurewebsites.net/.auth/login/apple', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ id_token: newAppleIdentityToken }),
      });
      if (reLoginResponse.ok) {
        const newAzureAuthData = await reLoginResponse.json();
        await SecureStore.setItemAsync('azureAccessToken', newAzureAuthData.access_token);
        await SecureStore.setItemAsync('azureRefreshToken', newAzureAuthData.refresh_token);
      } else {
        // 彻底失败,引导用户重新登录
      }
    }
  }
} catch (error) {
  console.error('Azure token refresh failed:', error);
}

4. 自动刷新时机

建议在以下场景触发刷新:

  • App启动时,检查Azure access_token的过期时间,若剩余时长不足1小时则触发刷新
  • 调用API返回401 Unauthorized时,自动尝试刷新令牌,刷新成功后重试API请求

关键注意事项

  • Apple的refreshToken有效期较长,但用户若在Apple设置中取消App授权,刷新会直接失败
  • Azure的refresh_token也有有效期,若Azure刷新失败,需用最新的Apple identityToken重新登录
  • 所有敏感凭证必须加密存储,禁止用明文AsyncStorage,优先使用expo-secure-store

内容的提问来源于stack exchange,提问作者user14002075

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:20:06