React Native library implementing Azure AD OAuth2 API
The library uses the latest V2.0 version of the Azure AD endponts and provides token cache functionality. react-native-azure-auth
implements authentication flow using fetch
API and native components. The OpenID connect and autorization_code
grant are implemented.
JS Docs can be accesed under https://vmurin.github.io/react-native-azure-auth/
Install react-native-azure-auth
using npm
npm install react-native-azure-auth --save
Or via yarn (recommended)
yarn add react-native-azure-auth
Then you need to link the native modules in react-native-azure-auth
and used AsyncStorage. Please check the link.
If you have used library before, it could be needed also to unlink the community version of AsyncStorage too.
Note: If you are using autolinking please be aware of caution to unlink the libraries in the autolinking docs. Especially if you are encountered the problem like issue #98
First, you will need to register your application with Microsoft Azure Portal. This will give you an Application ID for your application, as well as enable it to receive tokens.
Callback URLs are the URIs that Azure AD invokes after the authentication process. Azure routes your application back to this URI and appends additional parameters to it, including a token. Since callback URLs can be manipulated, you will need to add your application’s URL to your apps’s registered Redirect-URIs. This will enable Azure to recognize these URLs as valid. If omitted, authentication will not be successful.
{YOUR_BUNDLE_IDENTIFIER}://{YOUR_BUNDLE_IDENTIFIER}/ios/callback
{YOUR_APP_PACKAGE_NAME}://{YOUR_APP_PACKAGE_NAME}/android/callback
Note 1: Make sure to replace {YOUR_BUNDLE_IDENTIFIER} and {YOUR_APP_PACKAGE_NAME} with the actual values for your application.
Note 2: Be aware of allowed characters for the scheme part of URI. According to RFC 2396 (Section 3.1):
scheme = alpha *( alpha | digit | "+" | "-" | "." )
As you can see, allowed in identifier and package name underscore (_
) character is NOT allowed in the URI scheme!
In the file android/app/src/main/AndroidManifest.xml
you must make sure the MainActivity of the app has a launchMode value of singleTask
and that it has the following intent filter:
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPrefix="/${applicationId}/android/callback"
android:scheme="${applicationId}" />
</intent-filter>
The applicationId
here should be the same as your app package name, and not the ID from MS App Portal.
You would have the following MainActivity configuration:
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:pathPrefix="/android/callback"
android:host="${applicationId}"
android:scheme="${applicationId}" />
</intent-filter>
</activity>
For more info please read react native docs
Inside the ios
folder find the file AppDelegate.[swift|m]
add the following to it
// iOS 9.x or newer
#import <React/RCTLinkingManager.h>
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
return [RCTLinkingManager application:application openURL:url options:options];
}
If you’re targeting iOS 8.x or older, you can use the following code instead:
// iOS 8.x or older
#import <React/RCTLinkingManager.h>
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
return [RCTLinkingManager application:application openURL:url
sourceApplication:sourceApplication annotation:annotation];
}
Inside the ios
folder open the Info.plist
and locate the value for CFBundleIdentifier
, e.g.
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
The value
org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)
is the default for apps created with React Native CLI, you may have a different value.It is advisable to replace it with your own meaningfull ID in reverse DNS format. e.g. com.my-domain.native-app
and then register a URL type entry using the value of CFBundleIdentifier
as the value of CFBundleURLSchemes
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>None</string>
<key>CFBundleURLName</key>
<string>AzureAuth</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.my-domain.native-app</string>
</array>
</dict>
</array>
Attention: The
<string>
value forCFBundleURLSchemes
key MUST be the literal value of the Bundle Identifier with NO $-variables. In the example above the stringcom.my-domain.native-app
represents your Bundle Identifier.
For more info please read react native docs
import AzureAuth from 'react-native-azure-auth';
const azureAuth = new AzureAuth({
clientId: 'YOUR_CLIENT_ID'
});
try {
let tokens = await azureAuth.webAuth.authorize({scope: 'openid profile User.Read Mail.Read' })
this.setState({ accessToken: tokens.accessToken });
let info = await azureAuth.auth.msGraphRequest({token: tokens.accessToken, path: '/me'})
this.setState({ user: info.displayName, userId: tokens.userId })
} catch (error) {
console.log(error)
}
try {
// Try to get cached token or refresh an expired ones
let tokens = await azureAuth.auth.acquireTokenSilent({scope: 'Mail.Read', userId: this.state.userId})
if (!tokens) {
// No cached tokens or the requested scope defines new not yet consented permissions
// Open a window for user interaction
tokens = await azureAuth.webAuth.authorize({scope: 'Mail.Read'})
}
let mails = await azureAuth.auth.msGraphRequest({token: tokens.accessToken, path: '/me/mailFolders/Inbox/messages'})
} catch (error) {
console.log(error)
}
You can consult a tiny sample project react-native-azure-auth-sample for usage example
If you have found a bug or if you have a feature request, please report them at this repository issues section. Please take a little time and use search functionality of the issue tracker before posting a new issue, you can find some usefull infos in already closed issues. Please also do not report security vulnerabilities on the public GitHub issue tracker.
This project was originally inspired by https://github.com/auth0/react-native-auth0
Author: vmurin
Source Code: https://github.com/vmurin/react-native-azure-auth
#react-native #react #mobile-apps