Skip to content

Commit

Permalink
feat(msft): implement microsoft plugin (#11)
Browse files Browse the repository at this point in the history
* feat(msft): implement microsoft plugin

Signed-off-by: Kacper Wiszczuk <[email protected]>

* feat: cd for msft plugin

Signed-off-by: Kacper Wiszczuk <[email protected]>

* fix: remove unnecessary junk

Signed-off-by: Kacper Wiszczuk <[email protected]>

---------

Signed-off-by: Kacper Wiszczuk <[email protected]>
  • Loading branch information
Esemesek authored Apr 8, 2024
1 parent f1566b2 commit d753855
Show file tree
Hide file tree
Showing 23 changed files with 290 additions and 18 deletions.
5 changes: 4 additions & 1 deletion .github/workflows/cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ jobs:
echo GOOGLE_CLIENT_ID=${{ secrets.GOOGLE_CLIENT_ID }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties &&
echo FACEBOOK_APP_ID=${{ secrets.FACEBOOK_APP_ID }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties &&
echo FACEBOOK_CLIENT_TOKEN=${{ secrets.FACEBOOK_CLIENT_TOKEN }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties &&
echo DROPBOX_APP_KEY=${{ secrets.DROPBOX_APP_KEY }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties
echo DROPBOX_APP_KEY=${{ secrets.DROPBOX_APP_KEY }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties &&
echo MICROSOFT_CLIENT_ID=${{ secrets.MICROSOFT_CLIENT_ID }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties &&
echo MICROSOFT_HOST_PATH=com.openmobilehub.reactnative.auth.sample.MainApplication &&
echo MICROSOFT_SIGNATURE_HASH=${{ secrets.MICROSOFT_SIGNATURE_HASH }} >> ${{ env.SAMPLE_APP_PATH }}/local.properties
- name: Build release
run: |
Expand Down
1 change: 1 addition & 0 deletions apps/sample-app/android/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/src/main/res/raw/ms_auth_config.json
28 changes: 28 additions & 0 deletions apps/sample-app/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,34 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"

def properties = new Properties()
properties.load(project.rootProject.file("local.properties").newDataInputStream())

file("./src/main/res/raw/ms_auth_config.json").write(
"""
{
"client_id": "${properties.getProperty("MICROSOFT_CLIENT_ID")}",
"authorization_user_agent": "DEFAULT",
"redirect_uri": "msauth://${properties.getProperty("MICROSOFT_HOST_PATH")}/${
URLEncoder.encode(
properties.getProperty("MICROSOFT_SIGNATURE_HASH"),
"UTF-8"
)
}",
"authorities": [
{
"type": "AAD",
"audience": {
"type": "AzureADandPersonalMicrosoftAccount",
"tenant_id": "common"
}
}
],
"account_mode": "SINGLE"
}
""".strip().stripIndent()
)
}
signingConfigs {
debug {
Expand Down
Empty file.
1 change: 1 addition & 0 deletions apps/sample-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@omh/react-native-auth-google": "workspace:*",
"@omh/react-native-auth-facebook": "workspace:*",
"@omh/react-native-auth-dropbox": "workspace:*",
"@omh/react-native-auth-microsoft": "workspace:*",
"@react-native-async-storage/async-storage": "^1.23.1",
"@react-navigation/native": "^6.1.17",
"@react-navigation/native-stack": "^6.9.26",
Expand Down
14 changes: 11 additions & 3 deletions apps/sample-app/src/app/SignedInProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import React from 'react';
import DropboxAuth from '@omh/react-native-auth-dropbox';
import FacebookAuth from '@omh/react-native-auth-facebook';
import GoogleAuth from '@omh/react-native-auth-google';
import MicrosoftAuth from '@omh/react-native-auth-microsoft';
import AsyncStorage from '@react-native-async-storage/async-storage';

export const PROVIDER_NAMES = {
GOOGLE: 'google',
FACEBOOK: 'facebook',
DROPBOX: 'dropbox',
MICROSOFT: 'microsoft',
} as const;

type ObjectValues<T> = T[keyof T];
Expand All @@ -18,14 +20,20 @@ export type Providers = ObjectValues<typeof PROVIDER_NAMES>;
export const getAuthProvider = async (provider: Providers) => {
switch (provider) {
case PROVIDER_NAMES.GOOGLE:
await GoogleAuth.initialize(['openid', 'email', 'profile']);
await GoogleAuth.initialize({scopes: ['openid', 'email', 'profile']});
return GoogleAuth;
case PROVIDER_NAMES.FACEBOOK:
await FacebookAuth.initialize(['public_profile', 'email']);
await FacebookAuth.initialize({scopes: ['public_profile', 'email']});
return FacebookAuth;
case PROVIDER_NAMES.DROPBOX:
await DropboxAuth.initialize(['account_info.read']);
await DropboxAuth.initialize({scopes: ['account_info.read']});
return DropboxAuth;
case PROVIDER_NAMES.MICROSOFT:
await MicrosoftAuth.initialize({
scopes: ['User.Read'],
configFileName: 'ms_auth_config',
});
return MicrosoftAuth;
}
};

Expand Down
11 changes: 11 additions & 0 deletions apps/sample-app/src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,22 @@ export default function HomeScreen() {
signInWithProvider(PROVIDER_NAMES.DROPBOX);
}

async function onMicrosoftSignIn() {
const microsoftAuthProvider = await getAuthProvider(
PROVIDER_NAMES.MICROSOFT,
);

await microsoftAuthProvider.signIn();

signInWithProvider(PROVIDER_NAMES.MICROSOFT);
}

return (
<View style={styles.container}>
<Button onPress={onGoogleSignIn} title="Sign in with Google" />
<Button onPress={onFacebookSignIn} title="Sign in with Facebook" />
<Button onPress={onDropboxSignIn} title="Sign in with Dropbox" />
<Button onPress={onMicrosoftSignIn} title="Sign in with Microsoft" />
</View>
);
}
Expand Down
Binary file modified bun.lockb
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ import com.facebook.react.bridge.Promise
import com.facebook.react.bridge.ReactApplicationContext
import com.facebook.react.bridge.ReactContextBaseJavaModule
import com.facebook.react.bridge.ReactMethod
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.openmobilehub.android.auth.core.OmhAuthClient

class OmhAuthModule(
reactContext: ReactApplicationContext,
private val name: String,
private val createOmhAuthClient: (ArrayList<String>) -> OmhAuthClient
private val createOmhAuthClient: (config: HashMap<String, Any>) -> OmhAuthClient
) : ReactContextBaseJavaModule(reactContext) {
private var omhAuthClient: OmhAuthClient? = null

private fun getAuthClient(): OmhAuthClient {
if (omhAuthClient == null) {
throw Exception("OmhAuthClient is not initialized")
Expand All @@ -26,8 +25,8 @@ class OmhAuthModule(
return omhAuthClient!!
}

// TODO: Extract to separate class
private var loginActivityPromise: Promise? = null

private val activityEventListener =
object : BaseActivityEventListener() {
override fun onActivityResult(
Expand Down Expand Up @@ -62,8 +61,8 @@ class OmhAuthModule(
}

@ReactMethod
fun initialize(scopes: ReadableArray, promise: Promise) {
omhAuthClient = createOmhAuthClient(scopes.toArrayList() as ArrayList<String>)
fun initialize(config: ReadableMap, promise: Promise) {
omhAuthClient = createOmhAuthClient(config.toHashMap())

try {
getAuthClient().initialize().addOnSuccess {
Expand All @@ -89,7 +88,6 @@ class OmhAuthModule(

try {
val loginIntent = getAuthClient().getLoginIntent()

activity.startActivityForResult(loginIntent, LOGIN_REQUEST)
} catch (e: Exception) {
promise.reject(E_SIGN_IN_FAILED, e.message)
Expand Down
8 changes: 4 additions & 4 deletions packages/core/src/AuthModule.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {NativeModules} from 'react-native';

import {OmhUserProfile} from './types';
import {BaseAuthConfig, OmhUserProfile} from './types';

export default class AuthModule {
export default class AuthModule<C = BaseAuthConfig> {
authNativeModule: any;

constructor(moduleName: string) {
Expand All @@ -15,8 +15,8 @@ export default class AuthModule {
this.authNativeModule = authNativeModule;
}

initialize(scopes: Array<string>): Promise<void> {
return this.authNativeModule.initialize(scopes);
initialize(config: C): Promise<void> {
return this.authNativeModule.initialize(config);
}

signIn(): Promise<void> {
Expand Down
4 changes: 4 additions & 0 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
export type BaseAuthConfig = {
scopes: Array<string>;
};

export type OmhUserProfile = {
name?: string;
surname?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class OmhDropboxModule(private val reactContext: ReactApplicationContext) {
)
}

private fun createOmhAuthClient(scopes: ArrayList<String>): OmhAuthClient {
private fun createOmhAuthClient(config: HashMap<String, Any>): OmhAuthClient {
val scopes = config["scopes"] as ArrayList<String>

return DropboxAuthClient(
scopes = scopes,
context = reactContext,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ class OmhFacebookModule(private val reactContext: ReactApplicationContext) {
)
}

private fun createOmhAuthClient(scopes: ArrayList<String>): OmhAuthClient {
private fun createOmhAuthClient(config: HashMap<String, Any>): OmhAuthClient {
val scopes = config["scopes"] as ArrayList<String>

return FacebookAuthClient(
context = reactContext,
scopes = scopes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ class OmhGoogleModule(private val reactContext: ReactApplicationContext) {
)
}

private fun createOmhAuthClient(scopes: ArrayList<String>): OmhAuthClient {
private fun createOmhAuthClient(config: HashMap<String, Any>): OmhAuthClient {
val omhAuthProvider = OmhAuthProvider.Builder()
.addNonGmsPath("com.openmobilehub.android.auth.plugin.google.nongms.presentation.OmhAuthFactoryImpl")
.addGmsPath("com.openmobilehub.android.auth.plugin.google.gms.OmhAuthFactoryImpl")
.build()
val scopes = config["scopes"] as ArrayList<String>

return omhAuthProvider.provideAuthClient(
scopes = scopes,
Expand Down
106 changes: 106 additions & 0 deletions packages/plugin-microsoft/android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
buildscript {
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["OmhFacebook_kotlinVersion"]
def secrets_gradle_plugin = project.properties["OmhMicrosoft_secretsGradlePlugin"]

repositories {
google()
mavenCentral()
}

dependencies {
classpath "com.android.tools.build:gradle:7.2.1"
// noinspection DifferentKotlinGradleVersion
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

// Secrets Gradle Plugin
classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:$secrets_gradle_plugin"
}
}


def isNewArchitectureEnabled() {
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
}

apply plugin: "com.android.library"
apply plugin: "kotlin-android"

if (isNewArchitectureEnabled()) {
apply plugin: "com.facebook.react"
}

// Secrets Gradle Plugin
apply plugin: "com.google.android.libraries.mapsplatform.secrets-gradle-plugin"

def getExtOrDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["OmhMicrosoft_" + name]
}

def getExtOrIntegerDefault(name) {
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["OmhMicrosoft_" + name]).toInteger()
}

def supportsNamespace() {
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
def major = parsed[0].toInteger()
def minor = parsed[1].toInteger()

// Namespace support was added in 7.3.0
return (major == 7 && minor >= 3) || major >= 8
}

android {
if (supportsNamespace()) {
namespace "com.openmobilehub.reactnative.auth.plugin.microsoft"

sourceSets {
main {
manifest.srcFile "src/main/AndroidManifestNew.xml"
}
}
}

compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")

defaultConfig {
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")

}

buildTypes {
release {
minifyEnabled false
}
}

lintOptions {
disable "GradleCompatible"
}

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

repositories {
mavenCentral()
google()
}

def kotlin_version = getExtOrDefault("kotlinVersion")
def omh_microsoft_version = getExtOrDefault("omhMicrosoftVersion")

dependencies {
// For < 0.71, this will be from the local maven repo
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+"
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

// OMH
implementation "com.openmobilehub.android.auth:plugin-microsoft:$omh_microsoft_version"
api project(":omh-auth-core")
}
9 changes: 9 additions & 0 deletions packages/plugin-microsoft/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
OmhMicrosoft_kotlinVersion=1.7.0
OmhMicrosoft_minSdkVersion=21
OmhMicrosoft_targetSdkVersion=31
OmhMicrosoft_compileSdkVersion=31
OmhMicrosoft_ndkversion=21.4.7075529
# Secrets Gradle Plugin
OmhMicrosoft_secretsGradlePlugin=2.0.1
# OMH
OmhMicrosoft_omhMicrosoftVersion=2.0.0-beta
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.openmobilehub.reactnative.auth.plugin.microsoft">
</manifest>
19 changes: 19 additions & 0 deletions packages/plugin-microsoft/android/src/main/AndroidManifestNew.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="com.microsoft.identity.client.BrowserTabActivity"
android:exported="true">
<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:host="${MICROSOFT_HOST_PATH}"
android:path="/${MICROSOFT_SIGNATURE_HASH}"
android:scheme="msauth" />
</intent-filter>
</activity>
</application>
</manifest>
Loading

0 comments on commit d753855

Please sign in to comment.