image

Предисловие


Продолжение цикла по работе с Azure B2C. В данной статье я расскажу о том, как подключить аутентификацию на React Native.

Ссылки на связанные посты


ШАГ 1


Необходимо установить react-native-app-auth (npm i react-native-app-auth).

ШАГ 2


Открыть в Azure AD B2C ваше приложение. Во вкладке «Проверка подлинности» — нажать «Добавить платформу».

Необходимо выбрать Android и iOS.



После того, как вы создатие обе платформы вы полчите примерно такие данные:



ШАГ 3


Создать файл auth-provider.js в папке ./src

  import { authorize, revoke, refresh } from 'react-native-app-auth';
  const config = (page) => ({
    // Найти issuer можно во вкладке "Обзор". Для этого нажмите кнопку "Конечные точки".
    // Также необходимо добавить "tfp" как показано в примере ниже. 
    // В качестве параметра передаем нужную политику.
    issuer: `https://myapp.b2clogin.com/tfp/mycompany.onmicrosoft.com/${pages[page]}`,
    // ClientID вашего приложения Azure AD B2C
    clientId: '777aaa77a-7a77-7777-bb77-8888888aabc',
    scopes: ['openid'], // Обязательно укажите openid
    // Нужно для того, чтобы при повторной авторизации, пользователь мог 
    // снова выбрать способ авторизации (Google, Facebook и т.д.)
    additionalParameters: { prompt: 'login' },
    // URI перенаправления (Android)
    redirectUrl: 'msauth://com.myapp/asdasd%o293o4iro21342/',
  });
  const logOutConfig = {
    clientId: '777aaa77a-7a77-7777-bb77-8888888aabc',
    serviceConfiguration: {
      revocationEndpoint:
        'https://mycompany.b2clogin.com/mycompany.onmicrosoft.com/B2C_1A_SignIn/oauth2/v2.0/logout',
    },
  };
  // Используем отдельную политику для каждого действия
  const pages = {
    signIn: 'B2C_1A_SignIn',
    signUp: 'B2C_1A_SignUp',
    resetPassword: 'B2C_1A_PasswordReset',
  };

  // Функция для получения данных с Azure.
  const getAzureData = async (page) => {
    try {
      const data = await authorize(config(page));
      return data;
    } catch (e) {
      requestErrorHandler(e, 'azure authorize error');
    }
  };

  export const signIn = () => async (dispatch) => {
    const authMethod = 'signIn';
    try {
      const data = await getAzureData(authMethod);
      dispatch(userRegistration(data, authMethod));
    } catch (e) {
      requestErrorHandler(e, 'sign in error');
    }
  };


  export const azureLogOut = () => async (dispatch, getState) => {
    const { refreshToken } = getState().Authentication;
    try {
      await revoke(logOutConfig, {
        tokenToRevoke: refreshToken,
        sendClientId: true,
      });
      dispatch(authActions.logOut());
    } catch (e) {
      console.warn(e);
    }
  };

Где брать названия политик вы можете увидеть на скриншоте

image

ШАГ 4


Теперь нужно внести небольшие изменения в следующие файлы:

/android/app/build.gradle

  defaultConfig {
    manifestPlaceholders = [
        appAuthRedirectScheme: 'msauth'
    ]

    ...
  }

/ios/yourApp/Info.plist

<key>CFBundleURLTypes</key>
<array>
...
    <dict>
    <key>CFBundleURLName</key>
    <string>com.yourApp</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>msauth.com.yourApp</string>
    </array>
  </dict>
</array>

ШАГ 5


Теперь нам необходимо сохранить токен, что бы не просить пользователя авторизоваться каждый раз когда он открывает ваше приложение. Для этого необходимо скачать redux-persist-sensitive-storage.

(npm i redux-persist-sensitive-storage).

    import { compose, applyMiddleware, createStore } from "redux";
    import { persistStore, persistCombineReducers } from "redux-persist";
    import createSensitiveStorage from "redux-persist-sensitive-storage";
    import reducers from "./reducers"; // where reducers is an object of reducers

    const storage = createSensitiveStorage({
      keychainService: "myKeychain",
      sharedPreferencesName: "mySharedPrefs"
    });

    const config = {
      key: "root",
      storage,
    };

    const reducer = persistCombineReducers(config, reducers);

    function configureStore () {
      // ...
      let store = createStore(reducer);
      let persistor = persistStore(store);

      return { persistor, store };
    }
  


ШАГ 6


Добавляем функции для обновления токена

  export const autoSignIn = (params) => async (dispatch) => {
    try {
      const userData = await getRefreshedAzureUserData(params);
      await dispatch(openApplication(userData, params.authMethod));
    } catch (e) {
      requestErrorHandler(e, 'auto sign in error');
    }
  };
  export const getRefreshedAzureUserData = async ({ refreshToken, authMethod }) => {
    try {
      const result = await refresh(config(authMethod), { refreshToken });
      return result;
    } catch (e) {
      requestErrorHandler(e, 'get refresh token error');
    }
  };

Заключение


Вуаля. все готово! Теперь ваши пользователи смогут авторизовываться в вашем мобильном приложении.

Спасибо за внимание!