├── sample
├── .watchmanconfig
├── .gitattributes
├── android
│ ├── app
│ │ ├── src
│ │ │ ├── main
│ │ │ │ ├── res
│ │ │ │ │ ├── raw
│ │ │ │ │ │ └── index.html
│ │ │ │ │ ├── values
│ │ │ │ │ │ ├── strings.xml
│ │ │ │ │ │ └── styles.xml
│ │ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ │ └── mipmap-xxxhdpi
│ │ │ │ │ │ ├── ic_launcher.png
│ │ │ │ │ │ └── ic_launcher_round.png
│ │ │ │ ├── java
│ │ │ │ │ └── com
│ │ │ │ │ │ └── sample
│ │ │ │ │ │ ├── MainActivity.java
│ │ │ │ │ │ └── MainApplication.java
│ │ │ │ └── AndroidManifest.xml
│ │ │ └── debug
│ │ │ │ ├── AndroidManifest.xml
│ │ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── sample
│ │ │ │ └── ReactNativeFlipper.java
│ │ ├── debug.keystore
│ │ ├── proguard-rules.pro
│ │ ├── build_defs.bzl
│ │ ├── BUCK
│ │ └── build.gradle
│ ├── gradle
│ │ └── wrapper
│ │ │ ├── gradle-wrapper.jar
│ │ │ └── gradle-wrapper.properties
│ ├── settings.gradle
│ ├── build.gradle
│ ├── gradle.properties
│ ├── gradlew.bat
│ └── gradlew
├── app.json
├── babel.config.js
├── assets
│ ├── login.jpg
│ ├── footer.png
│ └── background.jpeg
├── ios
│ ├── sample
│ │ ├── Images.xcassets
│ │ │ ├── Contents.json
│ │ │ └── AppIcon.appiconset
│ │ │ │ └── Contents.json
│ │ ├── AppDelegate.h
│ │ ├── main.m
│ │ ├── Info.plist
│ │ ├── AppDelegate.m
│ │ └── LaunchScreen.storyboard
│ ├── sampleTests
│ │ ├── Info.plist
│ │ └── sampleTests.m
│ ├── sample-tvOSTests
│ │ └── Info.plist
│ ├── Podfile
│ ├── sample-tvOS
│ │ └── Info.plist
│ └── sample.xcodeproj
│ │ └── xcshareddata
│ │ └── xcschemes
│ │ ├── sample.xcscheme
│ │ └── sample-tvOS.xcscheme
├── .buckconfig
├── .prettierrc.js
├── __tests__
│ └── App-test.js
├── metro.config.js
├── tsconfig.json
├── components
│ ├── index.js
│ ├── ButtonContainer.js
│ ├── Button.js
│ └── styles.js
├── index.js
├── .gitignore
├── package.json
├── context
│ └── LoginContext.tsx
├── .flowconfig
├── App.tsx
├── screen
│ ├── HomeScreen.tsx
│ └── LoginScreen.tsx
└── .eslintrc.js
├── lib
├── babel.config.js
├── .npmignore
├── tsconfig.json
├── index.ts
├── .gitignore
├── package.json
├── src
│ ├── store.ts
│ ├── models.ts
│ ├── crypto-utils.ts
│ └── authenticate.tsx
├── .eslintrc.js
└── LICENSE
├── .github
├── config.yml
├── feature_request.md
├── improvement.md
├── doc_issues.md
├── bug_report.md
└── workflows
│ └── notification.yml
├── lerna.json
├── .gitignore
├── pull_request_template.md
├── LICENSE
└── README.md
/sample/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {}
--------------------------------------------------------------------------------
/sample/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
2 |
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/raw/index.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sample/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample",
3 | "displayName": "sample"
4 | }
--------------------------------------------------------------------------------
/lib/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [ "module:metro-react-native-babel-preset" ]
3 | };
4 |
--------------------------------------------------------------------------------
/sample/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [ "module:metro-react-native-babel-preset" ]
3 | };
4 |
--------------------------------------------------------------------------------
/sample/assets/login.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/assets/login.jpg
--------------------------------------------------------------------------------
/sample/assets/footer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/assets/footer.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | sample
3 |
4 |
--------------------------------------------------------------------------------
/sample/assets/background.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/assets/background.jpeg
--------------------------------------------------------------------------------
/sample/ios/sample/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/sample/android/app/debug.keystore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/debug.keystore
--------------------------------------------------------------------------------
/sample/.buckconfig:
--------------------------------------------------------------------------------
1 |
2 | [android]
3 | target = Google Inc.:Google APIs:23
4 |
5 | [maven_repositories]
6 | central = https://repo1.maven.org/maven2
7 |
--------------------------------------------------------------------------------
/sample/.prettierrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | bracketSpacing: false,
3 | jsxBracketSameLine: true,
4 | singleQuote: true,
5 | trailingComma: 'all',
6 | };
7 |
--------------------------------------------------------------------------------
/sample/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/lib/.npmignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | *.log
3 | npm-debug.log
4 |
5 | # Dependency directory
6 | node_modules
7 |
8 | # Runtime data
9 | tmp
10 |
11 | # Examples (If applicable to your project)
12 | examples
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wso2-attic/asgardeo-react-native-oidc-sdk/HEAD/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/sample/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'sample'
2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
3 | include ':app'
4 |
--------------------------------------------------------------------------------
/.github/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Ask a question
4 | url: https://github.com/wso2/product-is/wiki/Engage-with-the-community
5 | about: Check here on how you can ask a question about the product
6 |
--------------------------------------------------------------------------------
/sample/ios/sample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | @interface AppDelegate : UIResponder
5 |
6 | @property (nonatomic, strong) UIWindow *window;
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/sample/ios/sample/main.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import "AppDelegate.h"
4 |
5 | int main(int argc, char * argv[]) {
6 | @autoreleasepool {
7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/sample/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "command": {
4 | "version": {
5 | "message": "[Asgardeo Release] [GitHub Actions] [Release %s] Bump version"
6 | }
7 | },
8 | "packages": [
9 | "asgardio-react-native-oidc-sdk/*",
10 | "sample/*"
11 | ],
12 | "version": "0.1.0"
13 | }
14 |
--------------------------------------------------------------------------------
/sample/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/sample/__tests__/App-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import "react-native";
6 | import React from "react";
7 | import App from "../App";
8 |
9 | // Note: test renderer must be required after react-native.
10 | // eslint-disable-next-line import/order
11 | import renderer from "react-test-renderer";
12 |
13 | it("renders correctly", () => {
14 | renderer.create();
15 | });
16 |
--------------------------------------------------------------------------------
/sample/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/sample/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | module.exports = {
9 | transformer: {
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: false
14 | }
15 | })
16 | }
17 | };
18 |
--------------------------------------------------------------------------------
/sample/android/app/src/main/java/com/sample/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.sample;
2 |
3 | import com.facebook.react.ReactActivity;
4 |
5 | public class MainActivity extends ReactActivity {
6 |
7 | /**
8 | * Returns the name of the main component registered from JavaScript. This is used to schedule
9 | * rendering of the component.
10 | */
11 | @Override
12 | protected String getMainComponentName() {
13 | return "sample";
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/sample/android/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
--------------------------------------------------------------------------------
/.github/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ➕ Feature request
3 | about: Suggest an idea for this project
4 | title: ""
5 | labels: "feature"
6 | assignees: ""
7 | ---
8 |
9 | **Is your feature request related to a problem? Please describe.**
10 |
11 |
12 |
13 | **Describe the solution you would prefer**
14 |
15 |
16 |
17 | **Additional context**
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.github/improvement.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ✅ Improvement suggestion
3 | about: Suggest an improvement for the project
4 | title: ""
5 | labels: "improvement"
6 | assignees: ""
7 | ---
8 |
9 | **Is your suggestion related to an experience ? Please describe.**
10 |
11 |
12 |
13 | **Describe the improvement**
14 |
15 |
16 |
17 | **Additional context**
18 |
19 |
20 |
--------------------------------------------------------------------------------
/sample/android/app/build_defs.bzl:
--------------------------------------------------------------------------------
1 | """Helper definitions to glob .aar and .jar targets"""
2 |
3 | def create_aar_targets(aarfiles):
4 | for aarfile in aarfiles:
5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
6 | lib_deps.append(":" + name)
7 | android_prebuilt_aar(
8 | name = name,
9 | aar = aarfile,
10 | )
11 |
12 | def create_jar_targets(jarfiles):
13 | for jarfile in jarfiles:
14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
15 | lib_deps.append(":" + name)
16 | prebuilt_jar(
17 | name = name,
18 | binary_jar = jarfile,
19 | )
20 |
--------------------------------------------------------------------------------
/.github/doc_issues.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 📕 Doc issues
3 | about: Please report documentation issues here
4 | title: ""
5 | labels: "docs"
6 | assignees: ""
7 | ---
8 |
9 | **Is your suggestion related to a missing or misleading document? Please describe.**
10 |
11 |
12 |
13 | **Describe the improvement**
14 |
15 |
16 |
17 | ---
18 |
19 | ### Optional Fields
20 |
21 | **Additional context**
22 |
23 |
24 |
25 | **Related Issues:**
26 |
27 |
28 |
--------------------------------------------------------------------------------
/lib/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "es6",
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "noImplicitAny": false,
8 | "jsx": "react",
9 | "resolveJsonModule": true,
10 | "sourceMap": true,
11 | "noLib": false,
12 | "lib":["es5","es2017","dom"],
13 | "suppressImplicitAnyIndexErrors": true,
14 | "experimentalDecorators": true,
15 | "composite": true,
16 | "declarationMap": true,
17 | "baseUrl": "/",
18 | "paths": {
19 | "*": ["types/*"]
20 | },
21 |
22 | },
23 | "compileOnSave": false,
24 | "exclude": ["node_modules", "test-configs", "src/**/tests/*", "babel.config.js", "metro.config.js", "jest.config.js"]
25 | }
26 |
--------------------------------------------------------------------------------
/sample/ios/sample/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | }
33 | ],
34 | "info" : {
35 | "version" : 1,
36 | "author" : "xcode"
37 | }
38 | }
--------------------------------------------------------------------------------
/sample/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "es6",
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "noImplicitAny": false,
8 | "jsx": "react",
9 | "resolveJsonModule": true,
10 | "sourceMap": true,
11 | "noLib": false,
12 | "lib":["es5","es2017","dom"],
13 | "suppressImplicitAnyIndexErrors": true,
14 | "experimentalDecorators": true,
15 | "composite": true,
16 | "allowSyntheticDefaultImports": true,
17 | "declarationMap": true,
18 | "baseUrl": "/",
19 | "paths": {
20 | "*": ["types/*"]
21 | },
22 |
23 | },
24 | "compileOnSave": false,
25 | "exclude": ["node_modules", "test-configs", "src/**/tests/*", "babel.config.js", "metro.config.js", "jest.config.js"]
26 | }
27 |
--------------------------------------------------------------------------------
/sample/ios/sampleTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/sample/ios/sample-tvOSTests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/lib/index.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 | import { AuthClient, AuthProvider, useAuthContext } from "./src/authenticate";
19 |
20 | export { AuthClient, AuthProvider, useAuthContext };
21 |
--------------------------------------------------------------------------------
/sample/components/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | export { default as Button } from "./Button";
20 | export { default as ButtonContainer } from "./ButtonContainer";
21 |
--------------------------------------------------------------------------------
/sample/ios/Podfile:
--------------------------------------------------------------------------------
1 | require_relative '../node_modules/react-native/scripts/react_native_pods'
2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
3 |
4 | platform :ios, '10.0'
5 |
6 | target 'sample' do
7 | config = use_native_modules!
8 |
9 | use_react_native!(:path => config["reactNativePath"])
10 |
11 | target 'sampleTests' do
12 | inherit! :complete
13 | # Pods for testing
14 | end
15 |
16 | # Enables Flipper.
17 | #
18 | # Note that if you have use_frameworks! enabled, Flipper will not work and
19 | # you should disable these next few lines.
20 | use_flipper!
21 | post_install do |installer|
22 | flipper_post_install(installer)
23 | end
24 | end
25 |
26 | target 'sample-tvOS' do
27 | # Pods for sample-tvOS
28 |
29 | target 'sample-tvOSTests' do
30 | inherit! :search_paths
31 | # Pods for testing
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/sample/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import { AppRegistry } from "react-native";
20 | import App from "./App";
21 | import { name as appName } from "./app.json";
22 |
23 | AppRegistry.registerComponent(appName, () => App);
24 |
--------------------------------------------------------------------------------
/lib/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 | yarn-error.log
37 |
38 | # BUCK
39 | buck-out/
40 | \.buckd/
41 | *.keystore
42 | !debug.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | */fastlane/report.xml
52 | */fastlane/Preview.html
53 | */fastlane/screenshots
54 |
55 | # Bundle artifact
56 | *.jsbundle
57 |
58 | # CocoaPods
59 | /ios/Pods/
60 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 | project.xcworkspace
24 |
25 |
26 | # Android/IntelliJ
27 | #
28 | build/
29 | .idea
30 | .gradle
31 | local.properties
32 | *.iml
33 |
34 | # node.js
35 | #
36 | node_modules/
37 | npm-debug.log
38 | yarn-error.log
39 |
40 | # BUCK
41 | buck-out/
42 | \.buckd/
43 | *.keystore
44 | !debug.keystore
45 |
46 | # fastlane
47 | #
48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
49 | # screenshots whenever they are needed.
50 | # For more information about the recommended setup visit:
51 | # https://docs.fastlane.tools/best-practices/source-control/
52 |
53 | */fastlane/report.xml
54 | */fastlane/Preview.html
55 | */fastlane/screenshots
56 |
57 | # Bundle artifact
58 | *.jsbundle
59 |
60 | # CocoaPods
61 | /ios/Pods/
62 |
--------------------------------------------------------------------------------
/.github/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ❗️ Issue/Bug report
3 | about: Report issue or bug related to the project
4 | title: ""
5 | labels: "bug"
6 | assignees: ""
7 | ---
8 |
9 | **Describe the issue:**
10 |
11 |
12 |
13 | **How to reproduce:**
14 |
15 |
16 |
17 | **Expected behavior:**
18 |
19 |
20 |
21 | **Environment information** (_Please complete the following information; remove any unnecessary fields_) **:**
22 |
23 | - Product Version: [e.g., IS 5.10.0, IS 5.9.0]
24 | - OS: [e.g., Windows, Linux, Mac]
25 | - React Native Version: [e.g., 0.63, 0.62, 0.61]
26 | - Node version (node -v): [e.g., v15.2.1, v14.15.1, v12.19.1]
27 | - SDK Version: [e.g., 0.1.0, 0.1.1]
28 |
29 | ---
30 |
31 | ### Optional Fields
32 |
33 | **Related issues:**
34 |
35 |
36 |
37 | **Suggested labels:**
38 |
39 |
40 |
--------------------------------------------------------------------------------
/sample/android/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | buildToolsVersion = "29.0.2"
6 | minSdkVersion = 16
7 | compileSdkVersion = 29
8 | targetSdkVersion = 29
9 | }
10 | repositories {
11 | google()
12 | jcenter()
13 | }
14 | dependencies {
15 | classpath("com.android.tools.build:gradle:3.5.3")
16 | // NOTE: Do not place your application dependencies here; they belong
17 | // in the individual module build.gradle files
18 | }
19 | }
20 |
21 | allprojects {
22 | repositories {
23 | mavenLocal()
24 | maven {
25 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
26 | url("$rootDir/../node_modules/react-native/android")
27 | }
28 | maven {
29 | // Android JSC is installed from npm
30 | url("$rootDir/../node_modules/jsc-android/dist")
31 | }
32 |
33 | google()
34 | jcenter()
35 | maven { url 'https://www.jitpack.io' }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/sample/.gitignore:
--------------------------------------------------------------------------------
1 | # OSX
2 | #
3 | .DS_Store
4 |
5 | # Xcode
6 | #
7 | build/
8 | *.pbxuser
9 | !default.pbxuser
10 | *.mode1v3
11 | !default.mode1v3
12 | *.mode2v3
13 | !default.mode2v3
14 | *.perspectivev3
15 | !default.perspectivev3
16 | xcuserdata
17 | *.xccheckout
18 | *.moved-aside
19 | DerivedData
20 | *.hmap
21 | *.ipa
22 | *.xcuserstate
23 |
24 | # Android/IntelliJ
25 | #
26 | build/
27 | .idea
28 | .gradle
29 | local.properties
30 | *.iml
31 |
32 | # node.js
33 | #
34 | node_modules/
35 | npm-debug.log
36 | yarn-error.log
37 |
38 | # BUCK
39 | buck-out/
40 | \.buckd/
41 | *.keystore
42 | !debug.keystore
43 |
44 | # fastlane
45 | #
46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
47 | # screenshots whenever they are needed.
48 | # For more information about the recommended setup visit:
49 | # https://docs.fastlane.tools/best-practices/source-control/
50 |
51 | */fastlane/report.xml
52 | */fastlane/Preview.html
53 | */fastlane/screenshots
54 |
55 | # Bundle artifact
56 | *.jsbundle
57 |
58 | # CocoaPods
59 | /ios/Pods/
60 |
61 | # Certificate
62 | android/app/src/main/res/raw/wso2carbon.pem
63 |
64 | # IDE generated folders.
65 | /.vscode/
66 |
--------------------------------------------------------------------------------
/sample/components/ButtonContainer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import React from "react";
20 | import { StyleSheet, View } from "react-native";
21 |
22 | const ButtonContainer = props => ;
23 |
24 | const styles = StyleSheet.create({
25 | view: {
26 | alignSelf: "flex-end",
27 | bottom: 0,
28 | flexDirection: "row",
29 | left: 0,
30 | margin: 5,
31 | position: "absolute",
32 | right: 0
33 | }
34 | });
35 |
36 | export default ButtonContainer;
37 |
--------------------------------------------------------------------------------
/sample/android/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
20 | # AndroidX package structure to make it clearer which packages are bundled with the
21 | # Android operating system, and which are packaged with your app's APK
22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
23 | android.useAndroidX=true
24 | # Automatically convert third-party libraries to use AndroidX
25 | android.enableJetifier=true
26 |
27 | # Version of flipper SDK to use with React Native
28 | FLIPPER_VERSION=0.54.0
29 |
--------------------------------------------------------------------------------
/sample/components/Button.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import React from "react";
20 | import { StyleSheet, Text, TouchableOpacity } from "react-native";
21 |
22 | // eslint-disable-next-line react/prop-types
23 | const Button = ({ text, color, onPress }) => (
24 |
29 | { text }
30 |
31 | );
32 |
33 | const styles = StyleSheet.create({
34 | buttonBox: {
35 | alignItems: "center",
36 | flex: 1,
37 | height: 50,
38 | justifyContent: "center",
39 | margin: 5
40 | },
41 | text: {
42 | color: "white"
43 | }
44 | });
45 |
46 | export default Button;
47 |
--------------------------------------------------------------------------------
/sample/android/app/BUCK:
--------------------------------------------------------------------------------
1 | # To learn about Buck see [Docs](https://buckbuild.com/).
2 | # To run your application with Buck:
3 | # - install Buck
4 | # - `npm start` - to start the packager
5 | # - `cd android`
6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
8 | # - `buck install -r android/app` - compile, install and run application
9 | #
10 |
11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
12 |
13 | lib_deps = []
14 |
15 | create_aar_targets(glob(["libs/*.aar"]))
16 |
17 | create_jar_targets(glob(["libs/*.jar"]))
18 |
19 | android_library(
20 | name = "all-libs",
21 | exported_deps = lib_deps,
22 | )
23 |
24 | android_library(
25 | name = "app-code",
26 | srcs = glob([
27 | "src/main/java/**/*.java",
28 | ]),
29 | deps = [
30 | ":all-libs",
31 | ":build_config",
32 | ":res",
33 | ],
34 | )
35 |
36 | android_build_config(
37 | name = "build_config",
38 | package = "com.sample",
39 | )
40 |
41 | android_resource(
42 | name = "res",
43 | package = "com.sample",
44 | res = "src/main/res",
45 | )
46 |
47 | android_binary(
48 | name = "app",
49 | keystore = "//android/keystores:debug",
50 | manifest = "src/main/AndroidManifest.xml",
51 | package_type = "debug",
52 | deps = [
53 | ":app-code",
54 | ],
55 | )
56 |
--------------------------------------------------------------------------------
/sample/ios/sample-tvOS/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | NSAppTransportSecurity
26 |
27 | NSExceptionDomains
28 |
29 | localhost
30 |
31 | NSExceptionAllowsInsecureHTTPLoads
32 |
33 |
34 |
35 |
36 | NSLocationWhenInUseUsageDescription
37 |
38 | UILaunchStoryboardName
39 | LaunchScreen
40 | UIRequiredDeviceCapabilities
41 |
42 | armv7
43 |
44 | UISupportedInterfaceOrientations
45 |
46 | UIInterfaceOrientationPortrait
47 | UIInterfaceOrientationLandscapeLeft
48 | UIInterfaceOrientationLandscapeRight
49 |
50 | UIViewControllerBasedStatusBarAppearance
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/sample/ios/sample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | sample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1
25 | LSRequiresIPhoneOS
26 |
27 | NSAppTransportSecurity
28 |
29 | NSAllowsArbitraryLoads
30 |
31 | NSExceptionDomains
32 |
33 | localhost
34 |
35 | NSExceptionAllowsInsecureHTTPLoads
36 |
37 |
38 |
39 |
40 | NSLocationWhenInUseUsageDescription
41 |
42 | UILaunchStoryboardName
43 | LaunchScreen
44 | UIRequiredDeviceCapabilities
45 |
46 | armv7
47 |
48 | UISupportedInterfaceOrientations
49 |
50 | UIInterfaceOrientationPortrait
51 | UIInterfaceOrientationLandscapeLeft
52 | UIInterfaceOrientationLandscapeRight
53 |
54 | UIViewControllerBasedStatusBarAppearance
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/sample/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/sample/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sample",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start",
9 | "test": "jest",
10 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
11 | },
12 | "dependencies": {
13 | "@asgardeo/auth-react-native": "file:../lib/asgardeo-auth-react-native-0.0.1.tgz",
14 | "@react-native-async-storage/async-storage": "^1.13.2",
15 | "@react-native-community/masked-view": "^0.1.11",
16 | "@react-navigation/native": "^5.9.0",
17 | "@react-navigation/stack": "^5.13.0",
18 | "react": "16.13.1",
19 | "react-native": "^0.63.4",
20 | "react-native-gesture-handler": "^1.9.0",
21 | "react-native-reanimated": "^1.13.2",
22 | "react-native-safe-area-context": "^3.1.9",
23 | "react-native-screens": "^2.16.1",
24 | "react-native-webview": "^11.0.3",
25 | "reactotron-react-native": "^5.0.0",
26 | "text-encoding-polyfill": "^0.6.7"
27 | },
28 | "devDependencies": {
29 | "@babel/core": "^7.8.4",
30 | "@babel/runtime": "^7.8.4",
31 | "@types/jest": "^26.0.16",
32 | "@types/react": "^17.0.0",
33 | "@types/react-native": "^0.63.37",
34 | "@types/react-test-renderer": "^17.0.0",
35 | "@typescript-eslint/eslint-plugin": "^4.33.0",
36 | "@typescript-eslint/parser": "^4.33.0",
37 | "babel-jest": "^25.1.0",
38 | "eslint": "^7.32.0",
39 | "eslint-plugin-import": "^2.24.2",
40 | "eslint-plugin-react": "^7.27.1",
41 | "eslint-plugin-react-hooks": "^4.3.0",
42 | "jest": "^25.1.0",
43 | "metro-react-native-babel-preset": "^0.59.0",
44 | "react-test-renderer": "16.13.1",
45 | "typescript": "^4.1.2"
46 | },
47 | "jest": {
48 | "preset": "react-native",
49 | "moduleFileExtensions": [
50 | "ts",
51 | "tsx",
52 | "js",
53 | "jsx",
54 | "json",
55 | "node"
56 | ]
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/sample/ios/sampleTests/sampleTests.m:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 |
4 | #import
5 | #import
6 |
7 | #define TIMEOUT_SECONDS 600
8 | #define TEXT_TO_LOOK_FOR @"Welcome to React"
9 |
10 | @interface sampleTests : XCTestCase
11 |
12 | @end
13 |
14 | @implementation sampleTests
15 |
16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
17 | {
18 | if (test(view)) {
19 | return YES;
20 | }
21 | for (UIView *subview in [view subviews]) {
22 | if ([self findSubviewInView:subview matching:test]) {
23 | return YES;
24 | }
25 | }
26 | return NO;
27 | }
28 |
29 | - (void)testRendersWelcomeScreen
30 | {
31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
33 | BOOL foundElement = NO;
34 |
35 | __block NSString *redboxError = nil;
36 | #ifdef DEBUG
37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
38 | if (level >= RCTLogLevelError) {
39 | redboxError = message;
40 | }
41 | });
42 | #endif
43 |
44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
47 |
48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
50 | return YES;
51 | }
52 | return NO;
53 | }];
54 | }
55 |
56 | #ifdef DEBUG
57 | RCTSetLogFunction(RCTDefaultLogFunction);
58 | #endif
59 |
60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
62 | }
63 |
64 |
65 | @end
66 |
--------------------------------------------------------------------------------
/lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@asgardeo/auth-react-native",
3 | "description": "Asgardeo Auth React Native SDK for Mobile Applications.",
4 | "main": "index.ts",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1",
7 | "lint": "eslint . --ext .js,.jsx,.ts,.tsx"
8 | },
9 | "version": "0.0.1",
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/asgardeo/asgardeo-react-native-oidc-sdk.git"
13 | },
14 | "keywords": [
15 | "Asgardeo",
16 | "OIDC",
17 | "OAuth2",
18 | "Authentication",
19 | "Authorization",
20 | "React Native"
21 | ],
22 | "author": "Asgardeo",
23 | "license": "Apache-2.0",
24 | "bugs": {
25 | "url": "https://github.com/asgardeo/asgardeo-react-native-oidc-sdk/issues"
26 | },
27 | "homepage": "https://github.com/asgardeo/asgardeo-react-native-oidc-sdk#readme",
28 | "dependencies": {
29 | "@asgardeo/auth-js": "^1.0.0",
30 | "@react-native-async-storage/async-storage": "^1.13.2",
31 | "@types/crypto-js": "^4.0.1",
32 | "base-64": "^1.0.0",
33 | "crypto-js": "^3.3.0",
34 | "jsrsasign": "^10.5.1",
35 | "jsrsasign-util": "^1.0.5",
36 | "react": "16.13.1",
37 | "react-native": "^0.63.4",
38 | "react-native-gesture-handler": "^1.9.0",
39 | "url": "^0.11.0"
40 | },
41 | "deprecated": false,
42 | "devDependencies": {
43 | "@babel/core": "^7.8.4",
44 | "@babel/runtime": "^7.8.4",
45 | "@types/jest": "^26.0.16",
46 | "@types/react": "^17.0.0",
47 | "@types/react-native": "^0.63.37",
48 | "@types/react-test-renderer": "^17.0.0",
49 | "@typescript-eslint/eslint-plugin": "^4.33.0",
50 | "@typescript-eslint/parser": "^4.33.0",
51 | "babel-jest": "^25.1.0",
52 | "eslint": "^7.32.0",
53 | "eslint-plugin-import": "^2.24.2",
54 | "eslint-plugin-react": "^7.27.1",
55 | "eslint-plugin-react-hooks": "^4.3.0",
56 | "metro-react-native-babel-preset": "^0.65.1",
57 | "react-test-renderer": "16.13.1",
58 | "text-encoding-polyfill": "^0.6.7",
59 | "typescript": "^4.1.2"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sample/context/LoginContext.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import React, { useContext, useState } from "react";
20 |
21 | const initialState = {
22 | accessToken: "",
23 | allowedScopes: "",
24 | amr: "",
25 | at_hash: "",
26 | aud: "",
27 | azp: "",
28 | c_hash: "",
29 | exp: "",
30 | hasLogin: false,
31 | hasLogoutInitiated: false,
32 | iat: "",
33 | idToken: "",
34 | iss: "",
35 | loading: false,
36 | nbf: "",
37 | refreshToken: "",
38 | sessionState: "",
39 | sub: "",
40 | username: ""
41 | };
42 |
43 | const LoginContext = React.createContext(null);
44 |
45 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
46 | const LoginContextProvider = (
47 | props: { children: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal; }
48 | ) => {
49 | const [ loginState, setLoginState ] = useState(initialState);
50 | const [ loading, setLoading ] = useState(false);
51 |
52 | return (
53 |
61 | { props.children }
62 |
63 | );
64 | };
65 |
66 | const useLoginContext = (): any => {
67 | return useContext(LoginContext);
68 | };
69 |
70 | export { initialState, LoginContextProvider, useLoginContext };
71 |
--------------------------------------------------------------------------------
/sample/.flowconfig:
--------------------------------------------------------------------------------
1 | [ignore]
2 | ; We fork some components by platform
3 | .*/*[.]android.js
4 |
5 | ; Ignore "BUCK" generated dirs
6 | /\.buckd/
7 |
8 | ; Ignore polyfills
9 | node_modules/react-native/Libraries/polyfills/.*
10 |
11 | ; These should not be required directly
12 | ; require from fbjs/lib instead: require('fbjs/lib/warning')
13 | node_modules/warning/.*
14 |
15 | ; Flow doesn't support platforms
16 | .*/Libraries/Utilities/LoadingView.js
17 |
18 | [untyped]
19 | .*/node_modules/@react-native-community/cli/.*/.*
20 |
21 | [include]
22 |
23 | [libs]
24 | node_modules/react-native/interface.js
25 | node_modules/react-native/flow/
26 |
27 | [options]
28 | emoji=true
29 |
30 | esproposal.optional_chaining=enable
31 | esproposal.nullish_coalescing=enable
32 |
33 | module.file_ext=.js
34 | module.file_ext=.json
35 | module.file_ext=.ios.js
36 |
37 | munge_underscores=true
38 |
39 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1'
40 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub'
41 |
42 | suppress_type=$FlowIssue
43 | suppress_type=$FlowFixMe
44 | suppress_type=$FlowFixMeProps
45 | suppress_type=$FlowFixMeState
46 |
47 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)
48 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+
49 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError
50 |
51 | [lints]
52 | sketchy-null-number=warn
53 | sketchy-null-mixed=warn
54 | sketchy-number=warn
55 | untyped-type-import=warn
56 | nonstrict-import=warn
57 | deprecated-type=warn
58 | unsafe-getters-setters=warn
59 | unnecessary-invariant=warn
60 | signature-verification-failure=warn
61 | deprecated-utility=error
62 |
63 | [strict]
64 | deprecated-type
65 | nonstrict-import
66 | sketchy-null
67 | unclear-type
68 | unsafe-getters-setters
69 | untyped-import
70 | untyped-type-import
71 |
72 | [version]
73 | ^0.122.0
74 |
--------------------------------------------------------------------------------
/sample/App.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import "react-native-gesture-handler";
20 | import { AuthProvider } from "@asgardeo/auth-react-native";
21 | import { NavigationContainer } from "@react-navigation/native";
22 | import { createStackNavigator } from "@react-navigation/stack";
23 | import React from "react";
24 | import { LoginContextProvider } from "./context/LoginContext";
25 | import HomeScreen from "./screen/HomeScreen";
26 | import LoginScreen from "./screen/LoginScreen";
27 |
28 | const Stack = createStackNavigator();
29 |
30 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
31 | const App = () => {
32 |
33 | return (
34 |
35 |
36 |
37 |
38 |
43 |
48 |
49 |
50 |
51 |
52 | );
53 | };
54 |
55 | export default App;
56 |
--------------------------------------------------------------------------------
/lib/src/store.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import "text-encoding-polyfill";
20 | import { Store } from "@asgardeo/auth-js";
21 | import AsyncStorage from "@react-native-async-storage/async-storage";
22 |
23 | /**
24 | * Create a Store class to store the authentication data.
25 | * The following implementation uses the async-storage.
26 | */
27 | export class LocalStorage implements Store {
28 |
29 | /**
30 | * Get the data from the store.
31 | *
32 | * @param {string} key - key.
33 | *
34 | */
35 | async getData(key: string): Promise {
36 |
37 | const _value = await AsyncStorage.getItem(key);
38 |
39 | return _value;
40 | }
41 |
42 | /**
43 | * Save the data into the store.
44 | *
45 | * @param {string} key - key.
46 | * @param {string} value - value.
47 | *
48 | * @return {Promise}
49 | */
50 | async setData(key: string, value: string): Promise {
51 |
52 | try {
53 | await AsyncStorage.setItem(key, value);
54 | }
55 | catch(error) {
56 | // TODO: Add logs when a logger is available.
57 | // Tracked here https://github.com/asgardeo/asgardeo-auth-js-sdk/issues/151.
58 | }
59 | }
60 |
61 | /**
62 | * Remove the data from the store.
63 | *
64 | * @param {string} key - key.
65 | * @return {Promise}
66 | */
67 | async removeData(key: string): Promise {
68 |
69 | try {
70 | await AsyncStorage.removeItem(key);
71 | }
72 | catch(error) {
73 | // TODO: Add logs when a logger is available.
74 | // Tracked here https://github.com/asgardeo/asgardeo-auth-js-sdk/issues/151.
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/lib/src/models.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import {
20 | AuthClientConfig,
21 | BasicUserInfo,
22 | CustomGrantConfig,
23 | DataLayer,
24 | DecodedIDTokenPayload,
25 | GetAuthURLConfig,
26 | OIDCEndpoints,
27 | TokenResponse
28 | } from "@asgardeo/auth-js";
29 |
30 | export interface AuthStateInterface {
31 | accessToken: string;
32 | idToken: string;
33 | expiresIn: string;
34 | scope: string;
35 | refreshToken: string;
36 | tokenType: string;
37 | isAuthenticated: boolean;
38 | authResponseError?: {errorCode?: string, errorMessage?: string};
39 | }
40 |
41 | export interface AuthContextInterface {
42 | state: AuthStateInterface;
43 | isSignOutSuccessful: (signOutRedirectURL: string) => boolean;
44 | initialize: (config: AuthClientConfig) => Promise;
45 | getDataLayer: () => Promise>;
46 | getAuthorizationURL: (config?: GetAuthURLConfig) => Promise;
47 | signIn: (config?: GetAuthURLConfig) => Promise;
48 | refreshAccessToken: () => Promise;
49 | getSignOutURL: () => Promise;
50 | signOut: () => Promise;
51 | getOIDCServiceEndpoints: () => Promise;
52 | getDecodedIDToken: () => Promise;
53 | getBasicUserInfo: () => Promise;
54 | revokeAccessToken: () => Promise;
55 | getAccessToken: () => Promise;
56 | getIDToken: () => Promise;
57 | isAuthenticated: () => Promise;
58 | updateConfig: (config: Partial) => Promise;
59 | requestCustomGrant: (config: CustomGrantConfig) => Promise;
60 | clearAuthResponseError: () => void;
61 | }
62 |
63 | export type AuthUrl = {
64 | url: string
65 | }
66 |
--------------------------------------------------------------------------------
/sample/ios/sample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | #import "AppDelegate.h"
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #ifdef FB_SONARKIT_ENABLED
8 | #import
9 | #import
10 | #import
11 | #import
12 | #import
13 | #import
14 |
15 | static void InitializeFlipper(UIApplication *application) {
16 | FlipperClient *client = [FlipperClient sharedClient];
17 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
18 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
19 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
20 | [client addPlugin:[FlipperKitReactPlugin new]];
21 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
22 | [client start];
23 | }
24 | #endif
25 |
26 | @implementation AppDelegate
27 |
28 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
29 | {
30 | #ifdef FB_SONARKIT_ENABLED
31 | InitializeFlipper(application);
32 | #endif
33 |
34 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
35 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
36 | moduleName:@"sample"
37 | initialProperties:nil];
38 |
39 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
40 |
41 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
42 | UIViewController *rootViewController = [UIViewController new];
43 | rootViewController.view = rootView;
44 | self.window.rootViewController = rootViewController;
45 | [self.window makeKeyAndVisible];
46 | return YES;
47 | }
48 |
49 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
50 | {
51 | #if DEBUG
52 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
53 | #else
54 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
55 | #endif
56 | }
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Purpose
2 | > Describe the problems, issues, or needs driving this feature/fix and include links to related issues in the following format: Resolves issue1, issue2, etc.
3 |
4 | ## Goals
5 | > Describe the solutions that this feature/fix will introduce to resolve the problems described above
6 |
7 | ## Approach
8 | > Describe how you are implementing the solutions. Include an animated GIF or screenshot if the change affects the UI (email documentation@wso2.com to review all UI text). Include a link to a Markdown file or Google doc if the feature write-up is too long to paste here.
9 |
10 | ## User stories
11 | > Summary of user stories addressed by this change>
12 |
13 | ## Release note
14 | > Brief description of the new feature or bug fix as it will appear in the release notes
15 |
16 | ## Documentation
17 | > Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact
18 |
19 | ## Training
20 | > Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable
21 |
22 | ## Certification
23 | > Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.
24 |
25 | ## Marketing
26 | > Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable
27 |
28 | ## Automation tests
29 | - Unit tests
30 | > Code coverage information
31 | - Integration tests
32 | > Details about the test cases and coverage
33 |
34 | ## Security checks
35 | - Followed secure coding standards in http://wso2.com/technical-reports/wso2-secure-engineering-guidelines? yes/no
36 | - Ran FindSecurityBugs plugin and verified report? yes/no
37 | - Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets? yes/no
38 |
39 | ## Samples
40 | > Provide high-level details about the samples related to this feature
41 |
42 | ## Related PRs
43 | > List any other related PRs
44 |
45 | ## Migrations (if applicable)
46 | > Describe migration steps and platforms on which migration has been tested
47 |
48 | ## Test environment
49 | > List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested
50 |
51 | ## Learning
52 | > Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.
53 |
--------------------------------------------------------------------------------
/lib/src/crypto-utils.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import { CryptoUtils, DecodedIDTokenPayload, JWKInterface, SUPPORTED_SIGNATURE_ALGORITHMS } from "@asgardeo/auth-js";
20 | import { AsgardeoAuthException } from "@asgardeo/auth-js/src/exception";
21 | import { decode as atob } from "base-64";
22 | import Base64 from "crypto-js/enc-base64";
23 | import utf8 from "crypto-js/enc-utf8";
24 | import WordArray from "crypto-js/lib-typedarrays";
25 | import sha256 from "crypto-js/sha256";
26 | import { KEYUTIL, KJUR } from "jsrsasign";
27 |
28 | export class ReactNativeCryptoUtils implements CryptoUtils {
29 | /**
30 | * Get URL encoded string.
31 | *
32 | * @param {CryptoJS.WordArray} value.
33 | * @returns {string} base 64 url encoded value.
34 | */
35 | public base64URLEncode(value: WordArray): string {
36 | return Base64.stringify(value).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
37 | }
38 |
39 | public base64URLDecode(data: string): string {
40 | return Base64.parse(data).toString(utf8);
41 | }
42 |
43 | public hashSha256(data: string): WordArray {
44 | return sha256(data);
45 | }
46 |
47 | public generateRandomBytes(length: number): WordArray {
48 | return WordArray.random(length);
49 | }
50 |
51 | public parseJwk(key: Partial): Promise {
52 | return KEYUTIL.getKey({
53 | alg: key.alg,
54 | e: key.e,
55 | kty: key.kty,
56 | n: key.n
57 | });
58 | }
59 |
60 | public verifyJwt(
61 | idToken: string,
62 | jwk: any,
63 | algorithms: string[],
64 | clientID: string,
65 | issuer: string,
66 | subject: string,
67 | clockTolerance?: number
68 | ): Promise {
69 | const verification = KJUR.jws.JWS.verifyJWT(idToken, jwk, {
70 | alg: SUPPORTED_SIGNATURE_ALGORITHMS,
71 | aud: clientID,
72 | gracePeriod: clockTolerance,
73 | iss: [issuer],
74 | sub: subject
75 | });
76 |
77 | return Promise.resolve(verification);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/sample/android/app/src/main/java/com/sample/MainApplication.java:
--------------------------------------------------------------------------------
1 | package com.sample;
2 |
3 | import android.app.Application;
4 | import android.content.Context;
5 | import com.facebook.react.PackageList;
6 | import com.facebook.react.ReactApplication;
7 | import com.facebook.react.ReactInstanceManager;
8 | import com.facebook.react.ReactNativeHost;
9 | import com.facebook.react.ReactPackage;
10 | import com.facebook.soloader.SoLoader;
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.util.List;
13 |
14 | public class MainApplication extends Application implements ReactApplication {
15 |
16 | private final ReactNativeHost mReactNativeHost =
17 | new ReactNativeHost(this) {
18 | @Override
19 | public boolean getUseDeveloperSupport() {
20 | return BuildConfig.DEBUG;
21 | }
22 |
23 | @Override
24 | protected List getPackages() {
25 | @SuppressWarnings("UnnecessaryLocalVariable")
26 | List packages = new PackageList(this).getPackages();
27 | // Packages that cannot be autolinked yet can be added manually here, for example:
28 | // packages.add(new MyReactNativePackage());
29 | return packages;
30 | }
31 |
32 | @Override
33 | protected String getJSMainModuleName() {
34 | return "index";
35 | }
36 | };
37 |
38 | @Override
39 | public ReactNativeHost getReactNativeHost() {
40 | return mReactNativeHost;
41 | }
42 |
43 | @Override
44 | public void onCreate() {
45 | super.onCreate();
46 | SoLoader.init(this, /* native exopackage */ false);
47 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
48 | }
49 |
50 | /**
51 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like
52 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
53 | *
54 | * @param context
55 | * @param reactInstanceManager
56 | */
57 | private static void initializeFlipper(
58 | Context context, ReactInstanceManager reactInstanceManager) {
59 | if (BuildConfig.DEBUG) {
60 | try {
61 | /*
62 | We use reflection here to pick up the class that initializes Flipper,
63 | since Flipper library is not available in release mode
64 | */
65 | Class> aClass = Class.forName("com.sample.ReactNativeFlipper");
66 | aClass
67 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
68 | .invoke(null, context, reactInstanceManager);
69 | } catch (ClassNotFoundException e) {
70 | e.printStackTrace();
71 | } catch (NoSuchMethodException e) {
72 | e.printStackTrace();
73 | } catch (IllegalAccessException e) {
74 | e.printStackTrace();
75 | } catch (InvocationTargetException e) {
76 | e.printStackTrace();
77 | }
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/sample/components/styles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import { StyleSheet } from "react-native";
20 |
21 | const styles = StyleSheet.create({
22 | body: {
23 | margin: 10
24 | },
25 |
26 | button: {
27 | marginLeft: "35%",
28 | width: "30%"
29 | },
30 |
31 | deco: {
32 | fontWeight: "bold",
33 | margin: 10,
34 | textAlign: "center"
35 | },
36 |
37 | flex: {
38 | backgroundColor: "#e2e2e2",
39 | borderColor: "#c5c5c5",
40 | borderWidth: 1
41 | },
42 |
43 | flexBody: {
44 | fontWeight: "bold",
45 | marginLeft: 10
46 | },
47 |
48 | flexContainer: {
49 | flex: 1,
50 | flexDirection: "column",
51 | paddingBottom: 70
52 | },
53 |
54 | flexDetails: {
55 | marginBottom: 10,
56 | marginLeft: 10
57 | },
58 |
59 | flexHeading: {
60 | fontWeight: "bold",
61 | marginTop: 10,
62 | textAlign: "center"
63 | },
64 |
65 | footer: {
66 | alignItems: "center",
67 | paddingTop: 45
68 | },
69 |
70 | footerAlign: {
71 | height: 20,
72 | width: 50
73 | },
74 |
75 | image: {
76 | borderRadius: 30,
77 | height: "60%",
78 | resizeMode: "contain",
79 | width: "85%"
80 | },
81 |
82 | imageAlign: {
83 | alignItems: "center"
84 | },
85 |
86 | loading: {
87 | alignItems: "center",
88 | backgroundColor: "#F5FCFF88",
89 | bottom: 0,
90 | justifyContent: "center",
91 | left: 0,
92 | position: "absolute",
93 | right: 0,
94 | top: 0
95 | },
96 |
97 | mainBody: {
98 | backgroundColor: "#0000"
99 | },
100 |
101 | refBody: {
102 | textAlign: "center"
103 | },
104 |
105 | refToken: {
106 | marginBottom: 10,
107 | textAlign: "center"
108 | },
109 |
110 | text: {
111 | backgroundColor: "#f47421",
112 | borderBottomColor: "#e2e2e2",
113 | borderBottomWidth: 2,
114 | color: "white",
115 | fontSize: 25,
116 | justifyContent: "center",
117 | textAlign: "center"
118 | },
119 |
120 | textStyle: {
121 | color: "blue",
122 | textDecorationLine: "underline"
123 | },
124 |
125 | textpara: {
126 | borderBottomColor: "#282c34",
127 | color: "#2A2A2A",
128 | fontSize: 18,
129 | justifyContent: "center",
130 | paddingLeft: 20,
131 | paddingRight: 20,
132 | textAlign: "justify"
133 | }
134 | });
135 |
136 | export { styles };
137 |
--------------------------------------------------------------------------------
/sample/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto init
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto init
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :init
68 | @rem Get command-line arguments, handling Windows variants
69 |
70 | if not "%OS%" == "Windows_NT" goto win9xME_args
71 |
72 | :win9xME_args
73 | @rem Slurp the command line arguments.
74 | set CMD_LINE_ARGS=
75 | set _SKIP=2
76 |
77 | :win9xME_args_slurp
78 | if "x%~1" == "x" goto execute
79 |
80 | set CMD_LINE_ARGS=%*
81 |
82 | :execute
83 | @rem Setup the command line
84 |
85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
86 |
87 | @rem Execute Gradle
88 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
89 |
90 | :end
91 | @rem End local scope for the variables with windows NT shell
92 | if "%ERRORLEVEL%"=="0" goto mainEnd
93 |
94 | :fail
95 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
96 | rem the _cmd.exe /c_ return code!
97 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
98 | exit /b 1
99 |
100 | :mainEnd
101 | if "%OS%"=="Windows_NT" endlocal
102 |
103 | :omega
104 |
--------------------------------------------------------------------------------
/sample/android/app/src/debug/java/com/sample/ReactNativeFlipper.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) Facebook, Inc. and its affiliates.
3 | *
4 | *
This source code is licensed under the MIT license found in the LICENSE file in the root
5 | * directory of this source tree.
6 | */
7 | package com.sample;
8 |
9 | import android.content.Context;
10 | import com.facebook.flipper.android.AndroidFlipperClient;
11 | import com.facebook.flipper.android.utils.FlipperUtils;
12 | import com.facebook.flipper.core.FlipperClient;
13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping;
17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
22 | import com.facebook.react.ReactInstanceManager;
23 | import com.facebook.react.bridge.ReactContext;
24 | import com.facebook.react.modules.network.NetworkingModule;
25 | import okhttp3.OkHttpClient;
26 |
27 | public class ReactNativeFlipper {
28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
29 | if (FlipperUtils.shouldEnableFlipper(context)) {
30 | final FlipperClient client = AndroidFlipperClient.getInstance(context);
31 |
32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
33 | client.addPlugin(new ReactFlipperPlugin());
34 | client.addPlugin(new DatabasesFlipperPlugin(context));
35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context));
36 | client.addPlugin(CrashReporterPlugin.getInstance());
37 |
38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
39 | NetworkingModule.setCustomClientBuilder(
40 | new NetworkingModule.CustomClientBuilder() {
41 | @Override
42 | public void apply(OkHttpClient.Builder builder) {
43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
44 | }
45 | });
46 | client.addPlugin(networkFlipperPlugin);
47 | client.start();
48 |
49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
50 | // Hence we run if after all native modules have been initialized
51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
52 | if (reactContext == null) {
53 | reactInstanceManager.addReactInstanceEventListener(
54 | new ReactInstanceManager.ReactInstanceEventListener() {
55 | @Override
56 | public void onReactContextInitialized(ReactContext reactContext) {
57 | reactInstanceManager.removeReactInstanceEventListener(this);
58 | reactContext.runOnNativeModulesQueueThread(
59 | new Runnable() {
60 | @Override
61 | public void run() {
62 | client.addPlugin(new FrescoFlipperPlugin());
63 | }
64 | });
65 | }
66 | });
67 | } else {
68 | client.addPlugin(new FrescoFlipperPlugin());
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/sample/ios/sample.xcodeproj/xcshareddata/xcschemes/sample.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/sample/ios/sample.xcodeproj/xcshareddata/xcschemes/sample-tvOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
55 |
61 |
62 |
63 |
64 |
70 |
72 |
78 |
79 |
80 |
81 |
83 |
84 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/.github/workflows/notification.yml:
--------------------------------------------------------------------------------
1 | name: Send Notification
2 |
3 | on:
4 | issues:
5 | types: [opened]
6 | pull_request:
7 | types: [opened]
8 |
9 | jobs:
10 | notify:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Send notification on issue creation
14 | if: ${{github.event.issue}}
15 | run: |
16 | curl --location --request POST '${{secrets.WEBHOOK_CHAT}}' \
17 | --header 'Content-Type: application/json' \
18 | --data-raw '{
19 | "cards": [
20 | {
21 | "header": {
22 | "title": "ISSUE: ${{ github.event.issue.title }}",
23 | "subtitle": "By ${{ github.event.issue.user.login }} in Asgardeo React Native SDK Repo",
24 | "imageUrl": "https://avatars.githubusercontent.com/u/583231?v=4",
25 | "imageStyle": "IMAGE"
26 | },
27 | "sections": {
28 | "widgets": [
29 | {
30 | "buttons": [
31 | {
32 | "textButton": {
33 | "text": "Open Issue",
34 | "onClick": {
35 | "openLink": {
36 | "url": "${{ github.event.issue.html_url }}"
37 | }
38 | }
39 | }
40 | }
41 | ],
42 | "textParagraph": {
43 | "text": "${{ github.event.issue.body }}"
44 | }
45 | }
46 | ]
47 | }
48 | }
49 | ]
50 | }'
51 |
52 | - name: Send notification on pull request creation
53 | if: ${{github.event.pull_request}}
54 | run: |
55 | curl --location --request POST '${{secrets.WEBHOOK_CHAT}}' \
56 | --header 'Content-Type: application/json' \
57 | --data-raw '{
58 | "cards": [
59 | {
60 | "header": {
61 | "title": "PR: ${{ github.event.pull_request.title }}",
62 | "subtitle": "By ${{ github.event.pull_request.user.login }} in Asgardeo React Native SDK Repo",
63 | "imageUrl": "https://avatars.githubusercontent.com/u/583231?v=4",
64 | "imageStyle": "IMAGE"
65 | },
66 | "sections": {
67 | "widgets": [
68 | {
69 | "buttons": [
70 | {
71 | "textButton": {
72 | "text": "Open PR",
73 | "onClick": {
74 | "openLink": {
75 | "url": "${{ github.event.pull_request.html_url }}"
76 | }
77 | }
78 | }
79 | }
80 | ],
81 | "textParagraph": {
82 | "text": "${{ github.event.pull_request.body }}"
83 | }
84 | }
85 | ]
86 | }
87 | }
88 | ]
89 | }'
90 |
--------------------------------------------------------------------------------
/sample/screen/HomeScreen.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import { useAuthContext } from "@asgardeo/auth-react-native";
20 | import React from "react";
21 | import { ActivityIndicator, Text, View } from "react-native";
22 | import { ScrollView } from "react-native-gesture-handler";
23 | import { Button, ButtonContainer } from "../components";
24 | import { styles } from "../components/styles";
25 | import { useLoginContext } from "../context/LoginContext";
26 |
27 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
28 | const HomeScreen = () => {
29 |
30 | const { loginState, setLoginState, loading, setLoading } = useLoginContext();
31 | const { state, signOut, refreshAccessToken } = useAuthContext();
32 |
33 | /**
34 | * This function will handle the refresh button click.
35 | */
36 | const handleRefreshtoken = async () => {
37 |
38 | setLoading(true);
39 | refreshAccessToken()
40 | .catch((error) => {
41 | setLoading(false);
42 | // eslint-disable-next-line no-console
43 | console.log(error);
44 | });
45 | };
46 |
47 | /**
48 | * This function will handle the sign out button click.
49 | */
50 | const handleSignOut = async () => {
51 |
52 | setLoginState({
53 | ...loginState, ...state, hasLogoutInitiated: true
54 | });
55 |
56 | signOut()
57 | .catch((error) => {
58 | setLoading(false);
59 | // eslint-disable-next-line no-console
60 | console.log(error);
61 | });
62 | };
63 |
64 | return (
65 |
66 |
67 |
68 |
69 | Hi { loginState.username } !
70 |
71 |
72 | AllowedScopes : { loginState.allowedScopes }
73 |
74 | SessionState :
75 |
76 | { loginState.sessionState }
77 |
78 |
79 |
80 |
81 |
82 |
83 | Refresh token
84 | { loginState.refreshToken }
85 |
86 |
87 |
88 |
89 |
90 | Decoded ID token
91 | amr : { loginState.amr }, { "\n" }at_hash :
92 | { loginState.at_hash }, { "\n" }aud: { loginState.aud }, { "\n" }azp :
93 | { loginState.azp }, { "\n" }c_hash : { loginState.c_hash }, { "\n" }exp :
94 | { loginState.exp }, { "\n" }iat : { loginState.iat }, { "\n" }iss :
95 | { loginState.iss }, { "\n" }nbf : { loginState.nbf }, { "\n" }sub :
96 | { loginState.sub }
97 |
98 |
99 |
100 |
101 |
102 |
103 | ID token
104 | { loginState.idToken }
105 |
106 |
107 |
108 |
109 | {
110 | loading ?
111 | (
112 |
113 | ) : null
114 | }
115 |
116 |
117 |
118 |
119 |
120 |
121 | );
122 | };
123 |
124 | export default HomeScreen;
125 |
--------------------------------------------------------------------------------
/sample/ios/sample/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
25 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/sample/screen/LoginScreen.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import "text-encoding-polyfill";
20 | import { useAuthContext } from "@asgardeo/auth-react-native";
21 | import React, { useEffect } from "react";
22 | import { ActivityIndicator, Button, Image, Linking, Text, View } from "react-native";
23 | import { styles } from "../components/styles";
24 | import { initialState, useLoginContext } from "../context/LoginContext";
25 |
26 | // Create a config object containing the necessary configurations.
27 | const config = {
28 | clientID: "",
29 | serverOrigin: "https://10.0.2.2:9443",
30 | signInRedirectURL: "wso2sample://oauth2"
31 | };
32 |
33 | // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
34 | const LoginScreen = (props: { navigation: { navigate: (arg0: string) => void; }; }) => {
35 |
36 | const { loginState, setLoginState, loading, setLoading } = useLoginContext();
37 | const { state, initialize, signIn, getBasicUserInfo, getIDToken, getDecodedIDToken } = useAuthContext();
38 |
39 | /**
40 | * This hook will initialize the auth provider with the config object.
41 | */
42 | useEffect(() => {
43 | initialize(config);
44 | }, []);
45 |
46 | /**
47 | * This hook will listen for auth state updates and proceed.
48 | */
49 | useEffect(() => {
50 | if (state?.isAuthenticated) {
51 | const getData = async () => {
52 | try {
53 | const basicUserInfo = await getBasicUserInfo();
54 | const idToken = await getIDToken();
55 | const decodedIDToken = await getDecodedIDToken();
56 |
57 | setLoginState({
58 | ...loginState, ...state, ...basicUserInfo, idToken: idToken, ...decodedIDToken, hasLogin: true
59 | });
60 | setLoading(false);
61 | props.navigation.navigate("HomeScreen");
62 | } catch (error) {
63 | setLoading(false);
64 | // eslint-disable-next-line no-console
65 | console.log(error);
66 | }
67 | };
68 |
69 | getData();
70 | }else if (loginState.hasLogoutInitiated) {
71 | setLoginState(initialState);
72 | props.navigation.navigate("LoginScreen");
73 | }
74 | }, [ state.isAuthenticated ]);
75 |
76 | /**
77 | * This function will be triggered upon login button click.
78 | */
79 | const handleSubmitPress = async () => {
80 |
81 | setLoading(true);
82 | signIn()
83 | .catch((error: any) => {
84 | setLoading(false);
85 | // eslint-disable-next-line no-console
86 | console.log(error);
87 | });
88 | };
89 |
90 | return (
91 |
92 |
93 |
94 |
95 |
96 | React Native Authentication Sample{ " " }
97 |
98 |
99 |
100 |
104 |
105 | Sample demo to showcase authentication for a React Native via
106 | the OpenID Connect Authorization Code flow, which is integrated
107 | using the{ " " }
108 |
111 | Linking.openURL("https://github.com/asgardeo/asgardeo-react-native-oidc-sdk")
112 | }>
113 | Asgardeo Auth React Native SDK
114 |
115 | .
116 |
117 |
118 |
119 |
124 |
125 | {
126 | loading ?
127 | (
128 |
129 | ) : null
130 | }
131 |
132 |
133 |
134 |
138 |
139 |
140 |
141 | );
142 | };
143 |
144 | export default LoginScreen;
145 |
--------------------------------------------------------------------------------
/sample/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 | # Determine the Java command to use to start the JVM.
86 | if [ -n "$JAVA_HOME" ] ; then
87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
88 | # IBM's JDK on AIX uses strange locations for the executables
89 | JAVACMD="$JAVA_HOME/jre/sh/java"
90 | else
91 | JAVACMD="$JAVA_HOME/bin/java"
92 | fi
93 | if [ ! -x "$JAVACMD" ] ; then
94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
95 |
96 | Please set the JAVA_HOME variable in your environment to match the
97 | location of your Java installation."
98 | fi
99 | else
100 | JAVACMD="java"
101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
102 |
103 | Please set the JAVA_HOME variable in your environment to match the
104 | location of your Java installation."
105 | fi
106 |
107 | # Increase the maximum file descriptors if we can.
108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
109 | MAX_FD_LIMIT=`ulimit -H -n`
110 | if [ $? -eq 0 ] ; then
111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
112 | MAX_FD="$MAX_FD_LIMIT"
113 | fi
114 | ulimit -n $MAX_FD
115 | if [ $? -ne 0 ] ; then
116 | warn "Could not set maximum file descriptor limit: $MAX_FD"
117 | fi
118 | else
119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
120 | fi
121 | fi
122 |
123 | # For Darwin, add options to specify how the application appears in the dock
124 | if $darwin; then
125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
126 | fi
127 |
128 | # For Cygwin or MSYS, switch paths to Windows format before running java
129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
132 | JAVACMD=`cygpath --unix "$JAVACMD"`
133 |
134 | # We build the pattern for arguments to be converted via cygpath
135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
136 | SEP=""
137 | for dir in $ROOTDIRSRAW ; do
138 | ROOTDIRS="$ROOTDIRS$SEP$dir"
139 | SEP="|"
140 | done
141 | OURCYGPATTERN="(^($ROOTDIRS))"
142 | # Add a user-defined pattern to the cygpath arguments
143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
145 | fi
146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
147 | i=0
148 | for arg in "$@" ; do
149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
151 |
152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
154 | else
155 | eval `echo args$i`="\"$arg\""
156 | fi
157 | i=`expr $i + 1`
158 | done
159 | case $i in
160 | 0) set -- ;;
161 | 1) set -- "$args0" ;;
162 | 2) set -- "$args0" "$args1" ;;
163 | 3) set -- "$args0" "$args1" "$args2" ;;
164 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
165 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
166 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
167 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
168 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
169 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
170 | esac
171 | fi
172 |
173 | # Escape application args
174 | save () {
175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
176 | echo " "
177 | }
178 | APP_ARGS=`save "$@"`
179 |
180 | # Collect all arguments for the java command, following the shell quoting and substitution rules
181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
182 |
183 | exec "$JAVACMD" "$@"
184 |
--------------------------------------------------------------------------------
/sample/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "com.android.application"
2 |
3 | import com.android.build.OutputFile
4 |
5 | /**
6 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
7 | * and bundleReleaseJsAndAssets).
8 | * These basically call `react-native bundle` with the correct arguments during the Android build
9 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
10 | * bundle directly from the development server. Below you can see all the possible configurations
11 | * and their defaults. If you decide to add a configuration block, make sure to add it before the
12 | * `apply from: "../../node_modules/react-native/react.gradle"` line.
13 | *
14 | * project.ext.react = [
15 | * // the name of the generated asset file containing your JS bundle
16 | * bundleAssetName: "index.android.bundle",
17 | *
18 | * // the entry file for bundle generation. If none specified and
19 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is
20 | * // default. Can be overridden with ENTRY_FILE environment variable.
21 | * entryFile: "index.android.js",
22 | *
23 | * // https://reactnative.dev/docs/performance#enable-the-ram-format
24 | * bundleCommand: "ram-bundle",
25 | *
26 | * // whether to bundle JS and assets in debug mode
27 | * bundleInDebug: false,
28 | *
29 | * // whether to bundle JS and assets in release mode
30 | * bundleInRelease: true,
31 | *
32 | * // whether to bundle JS and assets in another build variant (if configured).
33 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
34 | * // The configuration property can be in the following formats
35 | * // 'bundleIn${productFlavor}${buildType}'
36 | * // 'bundleIn${buildType}'
37 | * // bundleInFreeDebug: true,
38 | * // bundleInPaidRelease: true,
39 | * // bundleInBeta: true,
40 | *
41 | * // whether to disable dev mode in custom build variants (by default only disabled in release)
42 | * // for example: to disable dev mode in the staging build type (if configured)
43 | * devDisabledInStaging: true,
44 | * // The configuration property can be in the following formats
45 | * // 'devDisabledIn${productFlavor}${buildType}'
46 | * // 'devDisabledIn${buildType}'
47 | *
48 | * // the root of your project, i.e. where "package.json" lives
49 | * root: "../../",
50 | *
51 | * // where to put the JS bundle asset in debug mode
52 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
53 | *
54 | * // where to put the JS bundle asset in release mode
55 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
56 | *
57 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
58 | * // require('./image.png')), in debug mode
59 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
60 | *
61 | * // where to put drawable resources / React Native assets, e.g. the ones you use via
62 | * // require('./image.png')), in release mode
63 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
64 | *
65 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
66 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
67 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle
68 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
69 | * // for example, you might want to remove it from here.
70 | * inputExcludes: ["android/**", "ios/**"],
71 | *
72 | * // override which node gets called and with what additional arguments
73 | * nodeExecutableAndArgs: ["node"],
74 | *
75 | * // supply additional arguments to the packager
76 | * extraPackagerArgs: []
77 | * ]
78 | */
79 |
80 | project.ext.react = [
81 | enableHermes: false, // clean and rebuild if changing
82 | ]
83 |
84 | apply from: "../../node_modules/react-native/react.gradle"
85 |
86 | /**
87 | * Set this to true to create two separate APKs instead of one:
88 | * - An APK that only works on ARM devices
89 | * - An APK that only works on x86 devices
90 | * The advantage is the size of the APK is reduced by about 4MB.
91 | * Upload all the APKs to the Play Store and people will download
92 | * the correct one based on the CPU architecture of their device.
93 | */
94 | def enableSeparateBuildPerCPUArchitecture = false
95 |
96 | /**
97 | * Run Proguard to shrink the Java bytecode in release builds.
98 | */
99 | def enableProguardInReleaseBuilds = false
100 |
101 | /**
102 | * The preferred build flavor of JavaScriptCore.
103 | *
104 | * For example, to use the international variant, you can use:
105 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
106 | *
107 | * The international variant includes ICU i18n library and necessary data
108 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
109 | * give correct results when using with locales other than en-US. Note that
110 | * this variant is about 6MiB larger per architecture than default.
111 | */
112 | def jscFlavor = 'org.webkit:android-jsc:+'
113 |
114 | /**
115 | * Whether to enable the Hermes VM.
116 | *
117 | * This should be set on project.ext.react and mirrored here. If it is not set
118 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
119 | * and the benefits of using Hermes will therefore be sharply reduced.
120 | */
121 | def enableHermes = project.ext.react.get("enableHermes", false);
122 |
123 | android {
124 | compileSdkVersion rootProject.ext.compileSdkVersion
125 |
126 | compileOptions {
127 | sourceCompatibility JavaVersion.VERSION_1_8
128 | targetCompatibility JavaVersion.VERSION_1_8
129 | }
130 |
131 | defaultConfig {
132 | applicationId "com.sample"
133 | minSdkVersion rootProject.ext.minSdkVersion
134 | targetSdkVersion rootProject.ext.targetSdkVersion
135 | versionCode 1
136 | versionName "1.0"
137 | }
138 | splits {
139 | abi {
140 | reset()
141 | enable enableSeparateBuildPerCPUArchitecture
142 | universalApk false // If true, also generate a universal APK
143 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
144 | }
145 | }
146 | signingConfigs {
147 | debug {
148 | storeFile file('debug.keystore')
149 | storePassword 'android'
150 | keyAlias 'androiddebugkey'
151 | keyPassword 'android'
152 | }
153 | }
154 | buildTypes {
155 | debug {
156 | signingConfig signingConfigs.debug
157 | }
158 | release {
159 | // Caution! In production, you need to generate your own keystore file.
160 | // see https://reactnative.dev/docs/signed-apk-android.
161 | signingConfig signingConfigs.debug
162 | minifyEnabled enableProguardInReleaseBuilds
163 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
164 | }
165 | }
166 |
167 | // applicationVariants are e.g. debug, release
168 | applicationVariants.all { variant ->
169 | variant.outputs.each { output ->
170 | // For each separate APK per architecture, set a unique version code as described here:
171 | // https://developer.android.com/studio/build/configure-apk-splits.html
172 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
173 | def abi = output.getFilter(OutputFile.ABI)
174 | if (abi != null) { // null for the universal-debug, universal-release variants
175 | output.versionCodeOverride =
176 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
177 | }
178 |
179 | }
180 | }
181 | }
182 |
183 | dependencies {
184 | implementation fileTree(dir: "libs", include: ["*.jar"])
185 | //noinspection GradleDynamicVersion
186 | implementation "com.facebook.react:react-native:+" // From node_modules
187 |
188 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
189 |
190 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
191 | exclude group:'com.facebook.fbjni'
192 | }
193 |
194 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
195 | exclude group:'com.facebook.flipper'
196 | exclude group:'com.squareup.okhttp3', module:'okhttp'
197 | }
198 |
199 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
200 | exclude group:'com.facebook.flipper'
201 | }
202 |
203 | if (enableHermes) {
204 | def hermesPath = "../../node_modules/hermes-engine/android/";
205 | debugImplementation files(hermesPath + "hermes-debug.aar")
206 | releaseImplementation files(hermesPath + "hermes-release.aar")
207 | } else {
208 | implementation jscFlavor
209 | }
210 | }
211 |
212 | // Run this once to be able to run the application with BUCK
213 | // puts all compile dependencies into folder libs for BUCK to use
214 | task copyDownloadableDepsToLibs(type: Copy) {
215 | from configurations.compile
216 | into 'libs'
217 | }
218 |
219 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
220 |
--------------------------------------------------------------------------------
/lib/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | const LINE_PADDING_RULES = [
20 | 1,
21 | // Add a new line after const, let, var declarations.
22 | { blankLine: "always", next: "*", prev: [ "const", "let", "var" ] },
23 | { blankLine: "any", next: [ "const", "let", "var" ], prev: [ "const", "let", "var" ] },
24 | // Add a new line after directive declarations like `use strict` etc.
25 | { blankLine: "always", next: "*", prev: "directive" },
26 | { blankLine: "any", next: "directive", prev: "directive" },
27 | // Add a new line before return statements.
28 | { blankLine: "always", next: "return", prev: "*" },
29 | // Add a new line try blocks.
30 | { blankLine: "always", next: "try", prev: "*" },
31 | // Add a new line break statements.
32 | { blankLine: "always", next: "break", prev: "*" },
33 | // Add a new line continue statements.
34 | { blankLine: "always", next: "continue", prev: "*" },
35 | // Add a new line before exports.
36 | { blankLine: "always", next: "export", prev: "*" },
37 | { blankLine: "any", next: "export", prev: "export" },
38 | // Add a new line before for loops.
39 | { blankLine: "always", next: "for", prev: "*" },
40 | // Add a new line before classes.
41 | { blankLine: "always", next: "class", prev: "*" },
42 | // Add a new line after import statements.
43 | { blankLine: "always", next: "*", prev: "import" },
44 | { blankLine: "any", next: "import", prev: "import" }
45 | ];
46 |
47 | module.exports = {
48 | env: {
49 | browser: true,
50 | es6: true,
51 | jest: true,
52 | node: true
53 | },
54 | extends: [
55 | "eslint:recommended",
56 | "plugin:react/recommended",
57 | "plugin:import/typescript",
58 | "plugin:react-hooks/recommended"
59 | ],
60 | globals: {
61 | JSX: false,
62 | // no-undef complains about globalThis @see {@link https://github.com/eslint/eslint/issues/11553}
63 | globalThis: false
64 | },
65 | overrides: [
66 | {
67 | env: {
68 | browser: true,
69 | es6: true,
70 | node: true
71 | },
72 | extends: [
73 | "eslint:recommended",
74 | "plugin:@typescript-eslint/eslint-recommended",
75 | "plugin:@typescript-eslint/recommended"
76 | ],
77 | files: [ "**/*.tsx", "**/*.ts" ],
78 | parser: "@typescript-eslint/parser",
79 | parserOptions: {
80 | ecmaVersion: 9,
81 | sourceType: "module"
82 | },
83 | rules: {
84 | "@typescript-eslint/ban-types": 1,
85 | "@typescript-eslint/explicit-function-return-type": 0,
86 | "@typescript-eslint/no-empty-function": [
87 | "error",
88 | {
89 | allow: [ "constructors" ]
90 | }
91 | ],
92 | "@typescript-eslint/no-explicit-any": 0,
93 | "@typescript-eslint/no-inferrable-types": "off",
94 | "@typescript-eslint/no-unused-vars": [
95 | "warn",
96 | {
97 | argsIgnorePattern: "^_",
98 | caughtErrorsIgnorePattern: "^_",
99 | varsIgnorePattern: "^_"
100 | }
101 | ],
102 | "@typescript-eslint/no-use-before-define": [
103 | "warn",
104 | {
105 | classes: false,
106 | functions: false,
107 | typedefs: false,
108 | variables: false
109 | }
110 | ],
111 | "@typescript-eslint/padding-line-between-statements": [ ...LINE_PADDING_RULES ],
112 | "eol-last": "error",
113 | // In development, error level is set to `warn`. This will be overridden
114 | // by the production env linting config.
115 | "no-debugger": 1,
116 | // `no-undef` is discouraged in Typescript projects.
117 | // https://github.com/typescript-eslint/typescript-eslint/issues/2477#issuecomment-686892459
118 | "no-undef": 0,
119 | "no-use-before-define": "off",
120 | "padding-line-between-statements": "off"
121 | },
122 | settings: {
123 | react: {
124 | version: "detect"
125 | }
126 | }
127 | }
128 | ],
129 | parserOptions: {
130 | ecmaVersion: 9,
131 | sourceType: "module"
132 | },
133 | plugins: [ "import" ],
134 | root: true,
135 | rules: {
136 | "array-bracket-spacing": [ 1, "always" ],
137 | "comma-dangle": [ "warn", "never" ],
138 | "eol-last": "error",
139 | "import/order": [
140 | "warn",
141 | {
142 | alphabetize: {
143 | caseInsensitive: true,
144 | order: "asc"
145 | },
146 | groups: [ "builtin", "external", "index", "sibling", "parent", "internal" ]
147 | }
148 | ],
149 | indent: [
150 | 1,
151 | 4,
152 | {
153 | SwitchCase: 1
154 | }
155 | ],
156 | "jsx-quotes": [ "warn", "prefer-double" ],
157 | "lines-between-class-members": [
158 | 1,
159 | "always",
160 | {
161 | exceptAfterSingleLine: true
162 | }
163 | ],
164 | "max-len": [
165 | "warn",
166 | {
167 | code: 120
168 | }
169 | ],
170 | "no-alert": 1,
171 | "no-console": "warn",
172 | "no-duplicate-imports": "warn",
173 | "no-restricted-imports": [
174 | "error",
175 | {
176 | paths: [
177 | {
178 | message: "Please use import foo from 'lodash-es/foo' instead.",
179 | name: "lodash"
180 | },
181 | {
182 | message: "Avoid using chain since it is non tree-shakable. Try out flow instead.",
183 | name: "lodash-es/chain"
184 | },
185 | {
186 | importNames: [ "chain" ],
187 | message: "Avoid using chain since it is non tree-shakable. Try out flow instead.",
188 | name: "lodash-es"
189 | },
190 | {
191 | message: "Please use import foo from 'lodash-es/foo' instead.",
192 | name: "lodash-es"
193 | }
194 | ],
195 | patterns: [ "@wso2is/**/dist/**", "lodash/**", "lodash/fp/**" ]
196 | }
197 | ],
198 | "no-unreachable": "error",
199 | "object-curly-spacing": [ "warn", "always" ],
200 | "padding-line-between-statements": [ ...LINE_PADDING_RULES ],
201 | quotes: [ "warn", "double" ],
202 | "react-hooks/exhaustive-deps": [ "off" ],
203 | "react/display-name": 0,
204 | "react/jsx-curly-spacing": [
205 | "warn",
206 | {
207 | allowMultiline: true,
208 | children: {
209 | when: "always"
210 | },
211 | spacing: {
212 | objectLiterals: "always"
213 | },
214 | when: "always"
215 | }
216 | ],
217 | "react/jsx-first-prop-new-line": [ 1, "multiline" ],
218 | "react/jsx-max-props-per-line": [
219 | 1,
220 | {
221 | maximum: 1,
222 | when: "multiline"
223 | }
224 | ],
225 | "react/jsx-wrap-multilines": [
226 | "warn",
227 | {
228 | arrow: "parens",
229 | assignment: "parens",
230 | condition: "parens",
231 | declaration: "parens",
232 | logical: "parens",
233 | prop: "parens",
234 | return: "parens"
235 | }
236 | ],
237 | "react/no-children-prop": 0,
238 | "react/prop-types": 1,
239 | semi: 1,
240 | "sort-imports": [
241 | "warn",
242 | {
243 | ignoreCase: false,
244 | ignoreDeclarationSort: true,
245 | ignoreMemberSort: false
246 | }
247 | ],
248 | "sort-keys": [
249 | "warn",
250 | "asc",
251 | {
252 | caseSensitive: true,
253 | minKeys: 2,
254 | natural: false
255 | }
256 | ]
257 | },
258 | settings: {
259 | react: {
260 | version: "detect"
261 | }
262 | }
263 | };
264 |
--------------------------------------------------------------------------------
/sample/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | const LINE_PADDING_RULES = [
20 | 1,
21 | // Add a new line after const, let, var declarations.
22 | { blankLine: "always", next: "*", prev: [ "const", "let", "var" ] },
23 | { blankLine: "any", next: [ "const", "let", "var" ], prev: [ "const", "let", "var" ] },
24 | // Add a new line after directive declarations like `use strict` etc.
25 | { blankLine: "always", next: "*", prev: "directive" },
26 | { blankLine: "any", next: "directive", prev: "directive" },
27 | // Add a new line before return statements.
28 | { blankLine: "always", next: "return", prev: "*" },
29 | // Add a new line try blocks.
30 | { blankLine: "always", next: "try", prev: "*" },
31 | // Add a new line break statements.
32 | { blankLine: "always", next: "break", prev: "*" },
33 | // Add a new line continue statements.
34 | { blankLine: "always", next: "continue", prev: "*" },
35 | // Add a new line before exports.
36 | { blankLine: "always", next: "export", prev: "*" },
37 | { blankLine: "any", next: "export", prev: "export" },
38 | // Add a new line before for loops.
39 | { blankLine: "always", next: "for", prev: "*" },
40 | // Add a new line before classes.
41 | { blankLine: "always", next: "class", prev: "*" },
42 | // Add a new line after import statements.
43 | { blankLine: "always", next: "*", prev: "import" },
44 | { blankLine: "any", next: "import", prev: "import" }
45 | ];
46 |
47 | module.exports = {
48 | env: {
49 | browser: true,
50 | es6: true,
51 | jest: true,
52 | node: true
53 | },
54 | extends: [
55 | "eslint:recommended",
56 | "plugin:react/recommended",
57 | "plugin:import/typescript",
58 | "plugin:react-hooks/recommended"
59 | ],
60 | globals: {
61 | JSX: false,
62 | // no-undef complains about globalThis @see {@link https://github.com/eslint/eslint/issues/11553}
63 | globalThis: false
64 | },
65 | overrides: [
66 | {
67 | env: {
68 | browser: true,
69 | es6: true,
70 | node: true
71 | },
72 | extends: [
73 | "eslint:recommended",
74 | "plugin:@typescript-eslint/eslint-recommended",
75 | "plugin:@typescript-eslint/recommended"
76 | ],
77 | files: [ "**/*.tsx", "**/*.ts" ],
78 | parser: "@typescript-eslint/parser",
79 | parserOptions: {
80 | ecmaVersion: 9,
81 | sourceType: "module"
82 | },
83 | rules: {
84 | "@typescript-eslint/ban-types": 1,
85 | "@typescript-eslint/explicit-function-return-type": 0,
86 | "@typescript-eslint/no-empty-function": [
87 | "error",
88 | {
89 | allow: [ "constructors" ]
90 | }
91 | ],
92 | "@typescript-eslint/no-explicit-any": 0,
93 | "@typescript-eslint/no-inferrable-types": "off",
94 | "@typescript-eslint/no-unused-vars": [
95 | "warn",
96 | {
97 | argsIgnorePattern: "^_",
98 | caughtErrorsIgnorePattern: "^_",
99 | varsIgnorePattern: "^_"
100 | }
101 | ],
102 | "@typescript-eslint/no-use-before-define": [
103 | "warn",
104 | {
105 | classes: false,
106 | functions: false,
107 | typedefs: false,
108 | variables: false
109 | }
110 | ],
111 | "@typescript-eslint/padding-line-between-statements": [ ...LINE_PADDING_RULES ],
112 | "eol-last": "error",
113 | // In development, error level is set to `warn`. This will be overridden
114 | // by the production env linting config.
115 | "no-debugger": 1,
116 | // `no-undef` is discouraged in Typescript projects.
117 | // https://github.com/typescript-eslint/typescript-eslint/issues/2477#issuecomment-686892459
118 | "no-undef": 0,
119 | "no-use-before-define": "off",
120 | "padding-line-between-statements": "off"
121 | },
122 | settings: {
123 | react: {
124 | version: "detect"
125 | }
126 | }
127 | }
128 | ],
129 | parserOptions: {
130 | ecmaVersion: 9,
131 | sourceType: "module"
132 | },
133 | plugins: [ "import" ],
134 | root: true,
135 | rules: {
136 | "array-bracket-spacing": [ 1, "always" ],
137 | "comma-dangle": [ "warn", "never" ],
138 | "eol-last": "error",
139 | "import/order": [
140 | "warn",
141 | {
142 | alphabetize: {
143 | caseInsensitive: true,
144 | order: "asc"
145 | },
146 | groups: [ "builtin", "external", "index", "sibling", "parent", "internal" ]
147 | }
148 | ],
149 | indent: [
150 | 1,
151 | 4,
152 | {
153 | SwitchCase: 1
154 | }
155 | ],
156 | "jsx-quotes": [ "warn", "prefer-double" ],
157 | "lines-between-class-members": [
158 | 1,
159 | "always",
160 | {
161 | exceptAfterSingleLine: true
162 | }
163 | ],
164 | "max-len": [
165 | "warn",
166 | {
167 | code: 120
168 | }
169 | ],
170 | "no-alert": 1,
171 | "no-console": "warn",
172 | "no-duplicate-imports": "warn",
173 | "no-restricted-imports": [
174 | "error",
175 | {
176 | paths: [
177 | {
178 | message: "Please use import foo from 'lodash-es/foo' instead.",
179 | name: "lodash"
180 | },
181 | {
182 | message: "Avoid using chain since it is non tree-shakable. Try out flow instead.",
183 | name: "lodash-es/chain"
184 | },
185 | {
186 | importNames: [ "chain" ],
187 | message: "Avoid using chain since it is non tree-shakable. Try out flow instead.",
188 | name: "lodash-es"
189 | },
190 | {
191 | message: "Please use import foo from 'lodash-es/foo' instead.",
192 | name: "lodash-es"
193 | }
194 | ],
195 | patterns: [ "@wso2is/**/dist/**", "lodash/**", "lodash/fp/**" ]
196 | }
197 | ],
198 | "no-unreachable": "error",
199 | "object-curly-spacing": [ "warn", "always" ],
200 | "padding-line-between-statements": [ ...LINE_PADDING_RULES ],
201 | quotes: [ "warn", "double" ],
202 | "react-hooks/exhaustive-deps": [ "off" ],
203 | "react/display-name": 0,
204 | "react/jsx-curly-spacing": [
205 | "warn",
206 | {
207 | allowMultiline: true,
208 | children: {
209 | when: "always"
210 | },
211 | spacing: {
212 | objectLiterals: "always"
213 | },
214 | when: "always"
215 | }
216 | ],
217 | "react/jsx-first-prop-new-line": [ 1, "multiline" ],
218 | "react/jsx-max-props-per-line": [
219 | 1,
220 | {
221 | maximum: 1,
222 | when: "multiline"
223 | }
224 | ],
225 | "react/jsx-wrap-multilines": [
226 | "warn",
227 | {
228 | arrow: "parens",
229 | assignment: "parens",
230 | condition: "parens",
231 | declaration: "parens",
232 | logical: "parens",
233 | prop: "parens",
234 | return: "parens"
235 | }
236 | ],
237 | "react/no-children-prop": 0,
238 | "react/prop-types": 1,
239 | semi: 1,
240 | "sort-imports": [
241 | "warn",
242 | {
243 | ignoreCase: false,
244 | ignoreDeclarationSort: true,
245 | ignoreMemberSort: false
246 | }
247 | ],
248 | "sort-keys": [
249 | "warn",
250 | "asc",
251 | {
252 | caseSensitive: true,
253 | minKeys: 2,
254 | natural: false
255 | }
256 | ]
257 | },
258 | settings: {
259 | react: {
260 | version: "detect"
261 | }
262 | }
263 | };
264 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/lib/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/lib/src/authenticate.tsx:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (c) 2021, WSO2 Inc. (http://www.wso2.com).
3 | *
4 | * WSO2 Inc. licenses this file to you under the Apache License,
5 | * Version 2.0 (the "License"); you may not use this file except
6 | * in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing,
12 | * software distributed under the License is distributed on an
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 | * KIND, either express or implied. See the License for the
15 | * specific language governing permissions and limitations
16 | * under the License.
17 | */
18 |
19 | import url from "url";
20 | import {
21 | AsgardeoAuthClient,
22 | AuthClientConfig,
23 | BasicUserInfo,
24 | CustomGrantConfig,
25 | DataLayer,
26 | DecodedIDTokenPayload,
27 | GetAuthURLConfig,
28 | OIDCEndpoints,
29 | TokenResponse
30 | } from "@asgardeo/auth-js";
31 | import { AsgardeoAuthException } from "@asgardeo/auth-js/src/exception";
32 | import React, { FunctionComponent, useContext, useEffect, useState } from "react";
33 | import { Linking } from "react-native";
34 | import { ReactNativeCryptoUtils } from "./crypto-utils";
35 | import { AuthContextInterface, AuthStateInterface, AuthUrl } from "./models";
36 | import { LocalStorage } from "./store";
37 |
38 | const initialState: AuthStateInterface = {
39 | accessToken: "",
40 | expiresIn: "",
41 | idToken: "",
42 | isAuthenticated: false,
43 | refreshToken: "",
44 | scope: "",
45 | tokenType: "",
46 | authResponseError: {}
47 | };
48 |
49 | // Instantiate the auth client object.
50 | const store = new LocalStorage();
51 | const cryptoUtils = new ReactNativeCryptoUtils();
52 | const AuthClient = new AsgardeoAuthClient(store, cryptoUtils);
53 |
54 | // Authentication Context to hold global states in react components.
55 | const AuthContext = React.createContext(null);
56 |
57 | const AuthProvider: FunctionComponent = (
58 | props: { children: boolean | React.ReactChild | React.ReactFragment | React.ReactPortal }
59 | ) => {
60 | const [ state, setState ] = useState(initialState);
61 |
62 | /**
63 | * This hook will register the url listener.
64 | */
65 | useEffect(() => {
66 | Linking.addEventListener("url", handleAuthRedirect);
67 |
68 | return () => {
69 | Linking.removeEventListener("url", handleAuthRedirect);
70 | };
71 | }, []);
72 |
73 | /**
74 | *
75 | * This method initializes the SDK with the config data.
76 | *
77 | * @param {AuthClientConfig} config - Authentication config object.
78 | * @return {Promise}
79 | *
80 | * @example
81 | * ```
82 | * initialize(config);
83 | * ```
84 | */
85 | const initialize = async (config: AuthClientConfig): Promise => {
86 |
87 | await AuthClient.initialize(config);
88 | };
89 |
90 | /**
91 | * This method returns the `DataLayer` object that allows you to access authentication data.
92 | *
93 | * @return {Promise>} - The `DataLayer` object.
94 | *
95 | * @example
96 | * ```
97 | * const data = await getDataLayer();
98 | * ```
99 | */
100 | const getDataLayer = async (): Promise> => {
101 |
102 | return await AuthClient.getDataLayer();
103 | };
104 |
105 | /**
106 | * This is an async method that returns a Promise which resolves with the authorization URL.
107 | *
108 | * @param {GetAuthURLConfig} config - Auth url config (optional).
109 | * @return {Promise} - A promise that resolves with the authorization URL.
110 | *
111 | * @example
112 | * ```
113 | * auth.getAuthorizationURL(config).then((url) => {
114 | * this.props.navigation.navigate("SignIn", {url:url,config:Config})
115 | * }).catch((error) => {
116 | * console.error(error);
117 | * });
118 | * ```
119 | */
120 | const getAuthorizationURL = async (config?: GetAuthURLConfig): Promise => {
121 |
122 | return await AuthClient.getAuthorizationURL(config);
123 | };
124 |
125 | /**
126 | * This function obtains the authorization url and perform the signin redirection.
127 | *
128 | * @return {Promise}
129 | *
130 | * @example
131 | * ```
132 | * signIn()
133 | * ```
134 | */
135 | const signIn = async (config?: GetAuthURLConfig): Promise => {
136 | await AuthClient.getAuthorizationURL(config)
137 | .then((url) => {
138 | Linking.openURL(url);
139 | })
140 | .catch((error) => {
141 | throw new AsgardeoAuthException(
142 | "AUTHENTICATE-SI-IV01",
143 | "authenticate",
144 | "signIn",
145 | "Failed to retrieve authorization url",
146 | error
147 | );
148 | });
149 | };
150 |
151 | /**
152 | * This is an method that sends a request to obtain the access token and returns a Promise
153 | * that resolves with the token and other relevant data.
154 | *
155 | * @param {AuthUrl} authUrl - The authorization url.
156 | *
157 | * @return {Promise} - A Promise that resolves with the token response.
158 | *
159 | * @example
160 | * ```
161 | * requestAccessTokenDetails(authUrl).then((token) => {
162 | * console.log("ReAccessToken", token);
163 | * setAuthState({...token});
164 | * }).catch((error) => {
165 | * console.log(error);
166 | * });
167 | * ```
168 | */
169 | const requestAccessTokenDetails = async (authUrl: AuthUrl): Promise => {
170 |
171 | const urlObject = url.parse(authUrl.url);
172 | const dataList = urlObject.query.split("&");
173 | const code = dataList[ 0 ].split("=")[ 1 ];
174 | const state = dataList[ 1 ].split("=")[ 1 ];
175 | const sessionState = dataList[ 2 ].split("=")[ 1 ];
176 |
177 | const authState = await AuthClient.requestAccessToken(code, sessionState, state);
178 |
179 | /**
180 | * TODO: Remove this waiting once https://github.com/asgardeo/asgardeo-auth-js-sdk/issues/164 is fixed.
181 | */
182 | await getAccessToken();
183 |
184 | setState({ ...authState, isAuthenticated: true });
185 |
186 | return authState;
187 | };
188 |
189 | /**
190 | * This method refreshes the access token and returns a Promise that resolves with the new access
191 | * token and other relevant data.
192 | *
193 | * @return {Promise} - A Promise that resolves with the token response.
194 | *
195 | * @example
196 | * ```
197 | * refreshAccessToken().then((response) => {
198 | * console.log(response);
199 | * }).catch((error) => {
200 | * console.error(error);
201 | * });
202 | * ```
203 | */
204 | const refreshAccessToken = async (): Promise => {
205 |
206 | setState({ ...state, isAuthenticated: false });
207 | const authState = await AuthClient.refreshAccessToken();
208 |
209 | setState({ ...authState, isAuthenticated: true });
210 |
211 | return authState;
212 | };
213 |
214 | /**
215 | * This method returns the sign-out URL.
216 | *
217 | * **This doesn't clear the authentication data.**
218 | *
219 | * @return {Promise} - A Promise that resolves with the sign-out URL.
220 | *
221 | * @example
222 | * ```
223 | * const signOutUrl = await getSignOutURL();
224 | * ```
225 | */
226 | const getSignOutURL = async (): Promise => {
227 |
228 | return await AuthClient.getSignOutURL();
229 | };
230 |
231 | /**
232 | * This method clears all authentication data and returns the sign-out URL.
233 | *
234 | * @return {Promise}
235 | *
236 | * @example
237 | * ```
238 | * signOut();
239 | * ```
240 | */
241 | const signOut = async (): Promise => {
242 |
243 | await AuthClient.getSignOutURL()
244 | .then((signOutUrl) => {
245 | Linking.openURL(signOutUrl);
246 | })
247 | .catch((error) => {
248 | throw new AsgardeoAuthException(
249 | "AUTHENTICATE-SO-IV01",
250 | "authenticate",
251 | "signOut",
252 | "Failed to retrieve signout url",
253 | error
254 | );
255 | });
256 | };
257 |
258 | /**
259 | * This method returns OIDC service endpoints that are fetched from the `.well-known` endpoint.
260 | *
261 | * @return {Promise} - A Promise that resolves with an object containing the OIDC service endpoints.
262 | *
263 | * @example
264 | * ```
265 | * const endpoints = await getOIDCServiceEndpoints();
266 | * ```
267 | */
268 | const getOIDCServiceEndpoints = async (): Promise => {
269 |
270 | return await AuthClient.getOIDCServiceEndpoints();
271 | };
272 |
273 | /**
274 | * This method decodes the payload of the ID token and returns it.
275 | *
276 | * @return {Promise} - A Promise that resolves with the decoded ID token payload.
277 | *
278 | * @example
279 | * ```
280 | * const decodedIdToken = await getDecodedIDToken();
281 | * ```
282 | *
283 | */
284 | const getDecodedIDToken = async (): Promise => {
285 |
286 | return await AuthClient.getDecodedIDToken();
287 | };
288 |
289 | /**
290 | * This method returns the basic user information obtained from the ID token.
291 | *
292 | * @return {Promise} - A Promise that resolves with an object containing the basic user information.
293 | *
294 | * @example
295 | * ```
296 | * const userInfo = await getBasicUserInfo();
297 | * ```
298 | */
299 | const getBasicUserInfo = async (): Promise => {
300 |
301 | return await AuthClient.getBasicUserInfo();
302 | };
303 |
304 | /**
305 | * This method revokes the access token.
306 | *
307 | * **This method also clears the authentication data.**
308 | *
309 | * @return {Promise} - A Promise that returns the response of the revoke-access-token request.
310 | *
311 | * @example
312 | * ```
313 | * revokeAccessToken().then((response)=>{
314 | * console.log(response);
315 | * }).catch((error)=>{
316 | * console.error(error);
317 | * });
318 | * ```
319 | */
320 | const revokeAccessToken = async (): Promise => {
321 |
322 | await AuthClient.revokeAccessToken()
323 | .then((response) => {
324 | setState(initialState);
325 |
326 | return Promise.resolve(response);
327 | })
328 | .catch((error) => {
329 | return Promise.reject(error);
330 | });
331 | };
332 |
333 | /**
334 | * This method returns the access token.
335 | *
336 | * @return {Promise} - A Promise that resolves with the access token.
337 | *
338 | * @example
339 | * ```
340 | * const accessToken = await getAccessToken();
341 | * ```
342 | */
343 | const getAccessToken = async (): Promise => {
344 |
345 | return await AuthClient.getAccessToken();
346 | };
347 |
348 | /**
349 | * This method returns the id token.
350 | *
351 | * @return {Promise} - A Promise that resolves with the id token.
352 | *
353 | * @example
354 | * ```
355 | * const idToken = await getIDToken();
356 | * ```
357 | */
358 | const getIDToken = async (): Promise => {
359 |
360 | return await AuthClient.getIDToken();
361 | };
362 |
363 | /**
364 | * This method returns if the user is authenticated or not.
365 | *
366 | * @return {Promise} - A Promise that resolves with `true` if the user is authenticated, `false` otherwise.
367 | *
368 | * @example
369 | * ```
370 | * await isAuthenticated();
371 | * ```
372 | */
373 | const isAuthenticated = async (): Promise => {
374 |
375 | return await AuthClient.isAuthenticated();
376 | };
377 |
378 | /**
379 | * This method returns the PKCE code generated during the generation of the authentication URL.
380 | *
381 | * @return {Promise} - A Promise that resolves with the PKCE code.
382 | *
383 | * @example
384 | * ```
385 | * const pkce = await getPKCECode();
386 | * ```
387 | */
388 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
389 | const getPKCECode = async (): Promise => {
390 |
391 | return await AuthClient.getPKCECode();
392 | };
393 |
394 | /**
395 | * This method sets the PKCE code to the data store.
396 | *
397 | * @param {string} pkce - The PKCE code.
398 | * @return {Promise}
399 | *
400 | * @example
401 | * ```
402 | * await setPKCECode("pkce_code")
403 | * ```
404 | */
405 | // eslint-disable-next-line @typescript-eslint/no-unused-vars
406 | const setPKCECode = async (pkce: string): Promise => {
407 |
408 | return await AuthClient.setPKCECode(pkce);
409 | };
410 |
411 | /**
412 | * This method returns if the sign-out is successful or not.
413 | *
414 | * @param {string} signOutRedirectUrl - The URL to which the user has been redirected to after signing-out.
415 | *
416 | * @return {boolean} - `true` if successful, `false` otherwise.
417 | *
418 | * @example
419 | * ```
420 | * const hasSignOut = isSignOutSuccessful("signOutRedirectURL");
421 | * ```
422 | */
423 | const isSignOutSuccessful = (signOutRedirectURL: string): boolean => {
424 |
425 | return AsgardeoAuthClient.isSignOutSuccessful(signOutRedirectURL);
426 | };
427 |
428 | /**
429 | * This method updates the configuration that was passed into the constructor when instantiating this class.
430 | *
431 | * @param {Partial} config - A config object to update the SDK configurations with.
432 | *
433 | * @example
434 | * ```
435 | * const config = {
436 | * clientID: "client ID",
437 | * serverOrigin: "https://localhost:9443"
438 | * }
439 | *
440 | * await updateConfig(config);
441 | */
442 | const updateConfig = async (config: Partial): Promise => {
443 |
444 | return await AuthClient.updateConfig(config);
445 | };
446 |
447 |
448 | /**
449 | * This method sends a custom-grant request and returns a Promise that resolves with the response
450 | * depending on the config passed.
451 | *
452 | * @param {CustomGrantConfig} config - A config object containing the custom grant configurations.
453 | *
454 | * @return {Promise} - A Promise that resolves with the response depending on your configurations.
455 | *
456 | * @example
457 | * ```
458 | * const config = {
459 | * attachToken: false,
460 | * data: {
461 | * client_id: "{{clientID}}",
462 | * grant_type: "account_switch",
463 | * scope: "{{scope}}",
464 | * token: "{{token}}",
465 | * },
466 | * id: "account-switch",
467 | * returnResponse: true,
468 | * returnsSession: true,
469 | * signInRequired: true
470 | * }
471 | *
472 | * requestCustomGrant(config).then((response) => {
473 | * console.log(response);
474 | * }).catch((error) => {
475 | * console.error(error);
476 | * });
477 | * ```
478 | */
479 | const requestCustomGrant = async (config: CustomGrantConfig): Promise => {
480 |
481 | return await AuthClient.requestCustomGrant(config);
482 | };
483 |
484 | /**
485 | * This function will handle authentication/ signout redirections.
486 | *
487 | * @param {AuthUrl} authUrl - redirection url.
488 | * @return {Promise}
489 | */
490 | const handleAuthRedirect = async (authUrl: AuthUrl): Promise => {
491 | try {
492 | if (url.parse(authUrl?.url)?.query.indexOf("code=") > -1) {
493 | await requestAccessTokenDetails(authUrl);
494 | } else if (url.parse(authUrl?.url)?.query.indexOf("state=sign_out") > -1) {
495 | const dataList = url.parse(authUrl?.url)?.query.split("&");
496 | const authState = dataList[0].split("=")[1];
497 |
498 | if (authState === "sign_out_success") {
499 | try {
500 | await AuthClient.getDataLayer().removeOIDCProviderMetaData();
501 | await AuthClient.getDataLayer().removeTemporaryData();
502 | await AuthClient.getDataLayer().removeSessionData();
503 | setState(initialState);
504 | } catch(error) {
505 | throw new AsgardeoAuthException(
506 | "AUTHENTICATE-HAR-IV01",
507 | "authenticate",
508 | "handleAuthRedirect",
509 | "Error in signout",
510 | error
511 | );
512 | }
513 | }
514 | } else if (url.parse(authUrl?.url)?.query.indexOf("error_description=") > -1) {
515 | const dataList = url.parse(authUrl?.url)?.query.split("&");
516 | const errorDescription = dataList[0].split("=")[1];
517 | const errorCode = dataList[2].split("=")[1];
518 | const errorMessage = errorDescription.split("+").join(" ");
519 |
520 | const error = { errorCode, errorMessage };
521 | setState({ ...state, authResponseError: error });
522 | } else {
523 | // TODO: Add logs when a logger is available.
524 | // Tracked here https://github.com/asgardeo/asgardeo-auth-js-sdk/issues/151.
525 | }
526 | } catch (error) {
527 | // TODO: Add logs when a logger is available.
528 | // Tracked here https://github.com/asgardeo/asgardeo-auth-js-sdk/issues/151.
529 | }
530 | };
531 |
532 | /**
533 | * This method clear the authentication response errors from state
534 | */
535 | const clearAuthResponseError = () : void => {
536 | setState({ ...state, authResponseError: {} });
537 | };
538 |
539 | return (
540 |
563 | { props.children }
564 |
565 | );
566 | };
567 |
568 | const useAuthContext = (): AuthContextInterface => {
569 | return useContext(AuthContext);
570 | };
571 |
572 | export { AuthClient, AuthProvider, useAuthContext };
573 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [DEPRECATED] Asgardeo React Native OIDC SDK & Samples
2 |
3 | ## :warning: Warning!
4 | ### React Native SDK is no longer encouraged and enriched by Asgardeo and may not work with the latest versions.
5 | ### You can implement login using [Authorization Code flow with PKCE](https://wso2.com/asgardeo/docs/guides/authentication/oidc/implement-auth-code-with-pkce/#prerequisites) with Asgardeo using OIDC standards.
6 |
7 | Repository containing the source of Asgardeo React Native OIDC SDK & Samples.
8 |
9 | [](https://stackoverflow.com/questions/tagged/wso2is)
10 | [](https://discord.gg/wso2)
11 | [](https://github.com/wso2/product-is/blob/master/LICENSE)
12 | [](https://twitter.com/intent/follow?screen_name=wso2)
13 |
14 | ---
15 |
16 | :construction: This project is a work in progress. Please do not use this yet!
17 |
18 | ## Table of Contents
19 |
20 | - [Introduction](#introduction)
21 | - [Install](#install)
22 | - [Getting Started](#getting-started)
23 | - [Configuring the Identity Server](#configuring-the-identity-server)
24 | - [Configuring the Sample](#configuring-the-sample)
25 | - [Running the Sample App](#running-the-sample-app)
26 | - [Running in an Android Emulator](#running-in-an-android-emulator)
27 | - [Running in an Android Device](#running-in-an-android-device)
28 | - [APIs](#apis)
29 | - [AuthProvider](#authprovider)
30 | - [useAuthContext](#useauthcontext)
31 | - [initialize](#initialize)
32 | - [getDataLayer](#getdatalayer)
33 | - [getAuthorizationURL](#getauthorizationurl)
34 | - [signIn](#signin)
35 | - [getAccessToken](#getaccesstoken)
36 | - [getBasicUserInfo](#getbasicuserinfo)
37 | - [getDecodedIDToken](#getdecodedidtoken)
38 | - [getIDToken](#getidtoken)
39 | - [getOIDCServiceEndpoints](#getoidcserviceendpoints)
40 | - [getSignOutUrl](#getsignouturl)
41 | - [signOut](#signout)
42 | - [revokeAccessToken](#revokeaccesstoken)
43 | - [refreshAccessToken](#refreshaccesstoken)
44 | - [isAuthenticated](#isauthenticated)
45 | - [isSignOutSuccessful](#issignoutsuccessful)
46 | - [requestCustomGrant](#requestcustomgrant)
47 | - [updateConfig](#updateconfig)
48 | - [Develop](#develop)
49 | - [Prerequisites](#prerequisites)
50 | - [Installing Dependencies](#installing-dependencies)
51 | - [Contribute](#contribute)
52 | - [Reporting Issues](#reporting-issues)
53 | - [License](#license)
54 |
55 | ## Introduction
56 |
57 | Asgardeo's OIDC SDK for React Native allows mobile applications to use OIDC or OAuth2 authentication in a simple and secure way. By using Asgardeo and the React Native OIDC SDK, mobile application developers will be able to add identity management to their mobile applications with more ease.
58 |
59 | ## Install
60 |
61 | Install the library from the npm registry.
62 | ```
63 | npm install --save @asgardeo/auth-react-native
64 | ```
65 |
66 | ## Getting Started
67 |
68 | You can experience the capabilities of Asgardeo React-native OIDC SDK by following this small guide which contains main
69 | sections listed below.
70 |
71 | - [Configuring the Identity Server](#configuring-the-identity-server)
72 | - [Configuring the Sample](#configuring-the-sample)
73 | - [Running the Sample App](#running-the-sample-app)
74 | - [Running in an Android Emulator](#running-in-an-android-emulator)
75 | - [Running in an Android Device](#running-in-an-android-device)
76 |
77 | ### Configuring the Identity Server
78 |
79 | 1. Start the WSO2 Identity server. If you haven't downloaded yet, please visit https://wso2.com/identity-server/ and download the latest version of the Identity server.
80 |
81 | 2. Create a service provider/ application in WSO2 IS and configure it following one of the procedures mentioned below.
82 |
83 | #### Approach 1
84 |
85 | 1. Login to WSO2 IS management console from https://localhost:9443/carbon/ and navigate to the **Service Providers** tab listed under the **Identity** section.
86 |
87 | 
88 |
89 | 2. Click **Add** to add a new service provider.
90 |
91 | 3. Provide a name for the Service Provider (ex:- sampleRN-app) and click **Register**. Now you will be redirected to the **Edit Service Provider** page.
92 |
93 | 4. Expand the **Inbound Authentication Configuration** section and click **Configure** under the **OAuth/OpenID Connect Configuration** section.
94 |
95 | 5. Under Allowed **Grant Types** uncheck everything except `Code` and `Refresh Token`.
96 |
97 | 6. Enter Callback URL(s) as for the following values.
98 |
99 | Callback Url: `wso2sample://oauth2`
100 |
101 | > Alternatively if you're running in an emulator, you can use `http://10.0.2.2:8081` as the callback url.
102 |
103 | 7. Check **Allow authentication without the client secret**.
104 |
105 | 8. Click **Add** button to add the OAuth configurations.
106 |
107 | 9. Once the configurations are added, you will be redirected to the **Service Provider Details** page. Here, expand the **Inbound Authentication Configuration** section and click on the **OAuth/OpenID Connect Configuration**. Copy the value of `OAuth Client Key` shown here.
108 |
109 | 
110 |
111 | 10. Make sure to click the `Update` button to save the changes.
112 |
113 | #### Approach 2
114 |
115 | Alternatively, you can create a **Custom Application** directly from the Identity Server Console.
116 |
117 | 1. Login to WSO2 IS console from https://localhost:9443/console/login and visit **Applications** section.
118 |
119 | 2. Click on **New Application** button and select the **Custom Application** template.
120 |
121 | 3. Provide a unique name to identify your application and click **Register** to complete the registration.
122 |
123 | 4. Go to the **Access** tab and click on **New Protocol** to start adding an authentication protocol.
124 |
125 | 5. Select **OpenID Connect** from the **Quick Setup** and click on **Next**.
126 |
127 | 6. Enter the Callback URL(s) as mentioned above and click **Next**.
128 |
129 | 7. Click **Finish** to save the configurations.
130 |
131 | 8. Under **Allowed grant type** check `Code` and `Refresh Token`.
132 |
133 | 9. Check **Public client** to allow the client to authenticate without a client secret.
134 |
135 | 10. Copy the value of `Client ID`. Make sure to click `Update` button to save the configurations.
136 |
137 | ### Configuring the Sample
138 |
139 | 1. Clone/download this project from `https://github.com/asgardeo/asgardeo-react-native-oidc-sdk.git`.
140 |
141 | 2. Install the dependencies and generate the tar file by running the following command inside the `lib/` directory.
142 |
143 | ```
144 | npm pack
145 | ```
146 |
147 | 3. Add the relevant configuratons to the **LoginScreen** file located at `sample/screen/LoginScreen` folder.
148 |
149 | - Replace the value of `clientID` with the value of `OAuth Client Key` or `Client ID` which you copied in the previous section of the documentation ([configuring the Identity Server](#configuring-the-identity-server)).
150 |
151 | ```TypeScript
152 | const config = {
153 | serverOrigin: 'https://{hostname}:9443',
154 | signInRedirectURL: 'http://{hostname}:{port}',
155 | clientID: 'ClientID',
156 | SignOutURL: "http://{hostname}:{port}" // (Optional)
157 | };
158 | ```
159 |
160 | Example:
161 |
162 | ```TypeScript
163 | const config = {
164 | serverOrigin: 'https://10.0.2.2:9443',
165 | signInRedirectURL: 'wso2sample://oauth2',
166 | clientID: 'iMc7TiIaIFafkd5hA5xf7kGiAWUa',
167 | SignOutURL: "http://10.0.2.2:8081" // (Optional)
168 | };
169 | ```
170 |
171 | 4. Install the required dependencies by running the following command inside the `sample/` directory.
172 |
173 | ```
174 | npm install
175 | ```
176 |
177 | ## Running the Sample App
178 |
179 | This application can be run either in an emulator or an actual device. Some configurations may differ depending on the OS.
180 |
181 | ### Android Setup
182 |
183 | 1. If the WSO2 IS is hosted in the local machine, you have to change the domain of the endpoints defined in `config` object at `screen/LoginScreen` file to `10.0.2.2`. Refer the documentation on [emulator-networking](https://developer.android.com/studio/run/emulator-networking). Next change the hostname of Identity server as `10.0.2.2` in the `/repository/conf/deployment.toml` file.
184 |
185 | 2. By default IS uses a self-signed certificate. If you ended up in SSL issues and are using the default pack without changing to a CA signed certificate, follow this [guide](https://developer.android.com/training/articles/security-config) to get rid of SSL issues.
186 |
187 | 3. Sometimes you may get `SSLHandshakeException` in android application since WSO2 IS is using a self-signed certificate. To fix this exception, you need to add the public certificate of IS to the sample application.
188 |
189 | i. Create a new keystore with CN as localhost and SAN as `10.0.2.2`.
190 |
191 | ```
192 | keytool -genkey -alias wso2carbon -keyalg RSA -keystore wso2carbon.jks -keysize 2048 -ext SAN=IP:10.0.2.2
193 | ```
194 |
195 | ii. Export the public certificate (ex: `wso2carbon.pem`) to add into the truststore.
196 |
197 | ```
198 | keytool -exportcert -alias wso2carbon -keystore wso2carbon.jks -rfc -file wso2carbon.pem
199 | ```
200 |
201 | iii. Import the certificate in the client-truststore.jks file located in `/repository/resources/security/`.
202 |
203 | ```
204 | keytool -import -alias wso2is -file wso2carbon.pem -keystore client-truststore.jks -storepass wso2carbon
205 | ```
206 |
207 | iv. Now copy this public certificate (`wso2carbon.pem`) to the `app/src/main/res/raw` folder.
208 |
209 | v. Create a new file named `network_security_config.xml` in `sample/android/app/src/main/res/xml` folder and copy the below content to it. Make sure to replace `wso2carbon` with the certificate name you added.
210 |
211 | ```xml
212 |
213 |
214 |
215 | localhost
216 | 10.0.2.2
217 |
218 |
219 |
220 | 192.168.43.29
221 |
222 |
223 |
224 | ```
225 |
226 | vi. Then add the following config to the `sample/android/app/src/main/AndroidManifest.xml` file under `application` section.
227 |
228 | ```xml
229 | android:networkSecurityConfig="@xml/network_security_config"
230 | ```
231 |
232 | Now the `AndroidManifest.xml` file should look like below.
233 | ```xml
234 |
235 |
236 |
240 | ...
241 |
242 |
243 | ```
244 |
245 | #### Running in an Android Emulator
246 |
247 | 1. Create a suitable Android virtual device using the **Android virtual device manager (AVD Manager)** and launch it.
248 |
249 | 2. Build and deploy the apps by running the following command at the root directory.
250 |
251 | ```bash
252 | react-native run-android
253 | ```
254 |
255 | #### Running in an Android Device
256 |
257 | 1. Enable **Debugging over USB** and plug in your device via USB.
258 |
259 | 2. Build and deploy the apps by running the following command at the root directory.
260 |
261 | ```bash
262 | react-native run-android
263 | ```
264 |
265 | > If you're running in a development or debugging mode, start the Metro by running the following command.
266 |
267 | ```bash
268 | react-native start
269 | ```
270 |
271 | ## APIs
272 |
273 | ### AuthProvider
274 |
275 | This is a React Context Provider that provides the session state that contains information such as the authenticated user's display name, email address, etc., and the methods that are required to implement authentication in the React native app.
276 | Like every other provider, the `AuthProvider` also encapsulates the components that would need the data provided by the provider.
277 |
278 | ---
279 |
280 | ### useAuthContext
281 |
282 | This is a React hook that returns the session state that contains information such as the email address of the authenticated user and the methods that are required for implementing authentication.
283 |
284 | #### Example
285 |
286 | ```typescript
287 | const { state, initialize, signIn } = useAuthContext();
288 | ```
289 |
290 | The object returned by the `useAuthContext` has a `state` attribute the value of which is an object of type [`AuthStateInterface`](#AuthStateInterface). You can refer the link to know more about what data is contained by the `state` object.
291 |
292 | In addition to the `state` object, the hook also returns the following methods.
293 |
294 | ---
295 |
296 | ### initialize
297 |
298 | ```TypeScript
299 | initialize: (config: AuthClientConfig) => Promise;
300 | ```
301 |
302 | #### Arguments
303 |
304 | 1. config: [`AuthClientConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#authclientconfigt) The config object containing the attributes that can be used to configure the SDK. To learn more about the available attributes, refer to [`AuthClientConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#authclientconfigt) model.
305 |
306 | #### Description
307 |
308 | This method initializes the auth client with the config data.
309 |
310 | #### Example
311 |
312 | ```TypeScript
313 | const config = {
314 | clientID: 'iMc7TiIaIFafkd5hA5xf7kGiAWUa',
315 | serverOrigin: 'https://10.0.2.2:9443',
316 | signInRedirectURL: 'wso2sample://oauth2'
317 | };
318 |
319 | await initialize(config);
320 | ```
321 |
322 | ---
323 |
324 | ### getDataLayer
325 |
326 | ```TypeScript
327 | getDataLayer: () => Promise>;
328 | ```
329 |
330 | #### Returns
331 |
332 | dataLayer: [`DataLayer`](https://github.com/asgardeo/asgardeo-auth-js-sdk#data-layer)
333 |
334 | A `DataLayer` object which wraps the `Store` object passed during object instantiation and provides access to various types of data used by the SDK. To learn more about the various types of interfaces provide by the `DataLayer`, refer to the [Data layer](https://github.com/asgardeo/asgardeo-auth-js-sdk#data-layer).
335 |
336 | #### Description
337 |
338 | This method returns DataLayer objects used by the SDK to store authentication data.
339 |
340 | #### Example
341 |
342 | ```TypeScript
343 | const _dataLayer = await getDataLayer();
344 | ```
345 |
346 | ---
347 |
348 | ### getAuthorizationURL
349 |
350 | ```TypeScript
351 | getAuthorizationURL: (config?: GetAuthURLConfig) => Promise;
352 | ```
353 |
354 | #### Arguments
355 |
356 | 1. config: [`GetAuthURLConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#getauthurlconfig) (optional) Config object that has the necessary attributes to configure this method. The `forceInit` attribute can be set to `true` to trigger a request to the `.well-known` endpoint and obtain the OIDC endpoints. By default, a request to the `.well-known` endpoint will be sent only if a request to it had not been sent before. If you wish to force a request to the endpoint, you can use this attribute.
357 |
358 | The object can only contain key-value pairs that you wish to append as path parameters to the authorization URL. For example, to set the `fidp` parameter, you can insert `fidp` as a key and its value to this object.
359 |
360 | #### Description
361 |
362 | This method returns a Promise that resolves with the authorization URL. The user can be redirected to this URL to authenticate themselves and authorize the client.
363 |
364 | #### Example
365 |
366 | ```TypeScript
367 | getAuthorizationURL(config).then((url) => {
368 | Linking.openURL(url);
369 | }).catch((error) => {
370 | console.error(error);
371 | });
372 | ```
373 |
374 | ---
375 |
376 | ### signIn
377 |
378 | ```TypeScript
379 | signIn: () => Promise;
380 | ```
381 |
382 | #### Description
383 |
384 | As the name implies, this method is used to sign-in users. This method will work in two phases. The first phase generates the authorization url and takes the user to the single-sign-on page of the identity server, while second phase triggers the token request to complete the authentication process. So, this method should be called when the user clicks on the **Sign in** button and should listen for the authentication state for state update inorder to proceed with the signin.
385 |
386 | #### Example
387 |
388 | ```TypeScript
389 | signIn()
390 | .catch((error: any) => {
391 | console.log(error);
392 | });
393 |
394 |
395 | useEffect(() => {
396 | // Steps after the authentication should come here.
397 | ...
398 | }, [ state.isAuthenticated ]);
399 | ```
400 |
401 | ---
402 |
403 | ### getAccessToken
404 |
405 | ```TypeScript
406 | getAccessToken: () => Promise;
407 | ```
408 |
409 | ### Returns
410 |
411 | accessToken: `Promise` A Promise that resolves with the access token.
412 |
413 | #### Description
414 |
415 | This method returns the access token stored in the store.
416 |
417 | #### Example
418 |
419 | ```TypeScript
420 | const accessToken = await getAccessToken();
421 | ```
422 |
423 | ---
424 |
425 | ### getBasicUserInfo
426 |
427 | ```TypeScript
428 | getBasicUserInfo: () => Promise;
429 | ```
430 |
431 | #### Returns
432 |
433 | basicUserInfo: Promise<[`BasicUserInfo`](https://github.com/asgardeo/asgardeo-auth-js-sdk#basicuserinfo)> An object containing basic user information obtained from the id token.
434 |
435 | #### Description
436 |
437 | This method returns the basic user information obtained from the payload. To learn more about what information is returned, checkout the [`BasicUserInfo`](https://github.com/asgardeo/asgardeo-auth-js-sdk#basicuserinfo) model.
438 |
439 | #### Example
440 |
441 | ```TypeScript
442 | const userInfo = await getBasicUserInfo();
443 | ```
444 |
445 | ---
446 |
447 | ### getDecodedIDToken
448 |
449 | ```TypeScript
450 | getDecodedIDToken: () => Promise;
451 | ```
452 |
453 | #### Returns
454 |
455 | decodedIDTokenPayload: Promise<[`DecodedIDTokenPayload`](https://github.com/asgardeo/asgardeo-auth-js-sdk#decodedidtokenpayload)> The decoded ID token payload.
456 |
457 | #### Description
458 |
459 | This method decodes the payload of the id token and returns the decoded values.
460 |
461 | #### Example
462 |
463 | ```TypeScript
464 | const decodedIdToken = await getDecodedIDToken();
465 | ```
466 |
467 | ---
468 |
469 | ### getIDToken
470 |
471 | ```TypeScript
472 | getIDToken: () => Promise;
473 | ```
474 |
475 | #### Returns
476 |
477 | idToken: `Promise` The id token.
478 |
479 | #### Description
480 |
481 | This method returns the id token.
482 |
483 | #### Example
484 |
485 | ```TypeScript
486 | const idToken = await getIDToken();
487 | ```
488 |
489 | ---
490 |
491 | ### getOIDCServiceEndpoints
492 |
493 | ```TypeScript
494 | getOIDCServiceEndpoints: () => Promise;
495 | ```
496 |
497 | #### Returns
498 |
499 | oidcEndpoints: Promise<[`OIDCEndpoints`](https://github.com/asgardeo/asgardeo-auth-js-sdk#oidcendpoints)>
500 |
501 | #### Description
502 |
503 | This method returns the OIDC service endpoints obtained from the `.well-known` endpoint.
504 |
505 | #### Example
506 |
507 | ```TypeScript
508 | const oidcEndpoints = await getOIDCServiceEndpoints();
509 | ```
510 |
511 | ---
512 |
513 | ### getSignOutUrl
514 |
515 | ```TypeScript
516 | getSignOutURL: () => Promise;
517 | ```
518 |
519 | #### Returns
520 |
521 | signOutURL: `Promise` Signout url
522 |
523 | #### Description
524 |
525 | This method returns the sign-out URL to which the user should be redirected to be signed out from the server.
526 | The user should be redirect to this URL in order to sign out from the server.
527 |
528 | #### Example
529 |
530 | ```TypeScript
531 | const signOutUrl = await getSignOutURL();
532 | Linking.openURL(signOutUrl);
533 | ```
534 |
535 | ---
536 |
537 | ### signOut
538 |
539 | ```TypeScript
540 | signOut: () => Promise;
541 | ```
542 |
543 | #### Description
544 |
545 | As the name implies, this method is used to sign-out users. This method will work in two phases. The first phase obtains the signout url and takes the user to the signout page of the identity server, while second phase clears the authentication data from the store upon successful sign out redirection. So, this method should be called when the user clicks on the **Sign out** button and should listen for the authentication state for state update inorder to proceed with the signout.
546 |
547 | #### Example
548 |
549 | ```TypeScript
550 | signOut()
551 | .catch((error) => {
552 | console.log(error);
553 | });
554 | ```
555 |
556 | ---
557 |
558 | ### revokeAccessToken
559 |
560 | ```TypeScript
561 | revokeAccessToken: () => Promise;
562 | ```
563 |
564 | #### Returns
565 |
566 | A Promise that resolves with the response returned by the server.
567 |
568 | #### Description
569 |
570 | This method clears the authentication data and sends a request to revoke the access token. You can use this method if you want to sign the user out of your application but not from the server.
571 |
572 | #### Example
573 |
574 | ```TypeScript
575 | revokeAccessToken().then((response) => {
576 | console.log(response);
577 | }).catch((error) => {
578 | console.error(error);
579 | })
580 | ```
581 |
582 | ---
583 |
584 | ### refreshAccessToken
585 |
586 | ```TypeScript
587 | refreshAccessToken: () => Promise;
588 | ```
589 |
590 | #### Returns
591 |
592 | A Promise that resolves with the token response that contains the token information.
593 |
594 | #### Description
595 |
596 | This method sends a refresh-token request and returns a promise that resolves with the token response that contains the token information. To learn more about what information is returned, checkout the [`TokenResponse`](https://github.com/asgardeo/asgardeo-auth-js-sdk#tokenresponse) model. You could listen for the authentication state for state update inorder to proceed.
597 |
598 | #### Example
599 |
600 | ```TypeScript
601 | refreshAccessToken()
602 | .catch((error) => {
603 | console.log(error);
604 | });
605 | ```
606 |
607 | ---
608 |
609 | ### isAuthenticated
610 |
611 | ```TypeScript
612 | isAuthenticated: () => Promise;
613 | ```
614 |
615 | #### Returns
616 |
617 | isAuthenticated: `Promise` A boolean value that indicates if the user is authenticated or not.
618 |
619 | #### Description
620 |
621 | This method returns a boolean value indicating if the user is authenticated or not.
622 |
623 | #### Example
624 |
625 | ```TypeScript
626 | const isAuth = await isAuthenticated();
627 | ```
628 |
629 | ---
630 |
631 | ### isSignOutSuccessful
632 |
633 | ```TypeScript
634 | isSignOutSuccessful: (signOutRedirectURL: string) => boolean;
635 | ```
636 |
637 | #### Arguments
638 |
639 | 1. signOutRedirectURL: `string` The URL to which the user is redirected to after signing out from the server.
640 |
641 | #### Description
642 |
643 | This method returns if the user has been successfully signed out or not. When a user signs out from the server, the user is redirected to the URL specified by the `signOutRedirectURL` in the config object passed into the `initialize` function. The server appends path parameters indicating if the sign-out is successful. This method reads the URL and returns if the sign-out is successful or not. So, make sure you pass as the argument, the URL to which the user has been redirected to after signing out from the server.
644 |
645 | #### Example
646 |
647 | ```TypeScript
648 | const hasSignOut = isSignOutSuccessful("signOutRedirectURL");
649 | ```
650 |
651 | ---
652 |
653 | ### requestCustomGrant
654 |
655 | ```TypeScript
656 | requestCustomGrant: (config: CustomGrantConfig) => Promise;
657 | ```
658 |
659 | #### Arguments
660 |
661 | 1. config: [`CustomGrantConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#customgrantconfig) The config object contains attributes that would be used to configure the custom grant request. To learn more about the different configurations available, checkout the [`CustomGrantConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#customgrantconfig) model.
662 |
663 | #### Returns
664 |
665 | A Promise that resolves with the token information or the response returned by the server depending on the configuration passed.
666 |
667 | #### Description
668 |
669 | This method can be used to send custom-grant requests to Asgardeo.
670 |
671 | #### Example
672 |
673 | ```TypeScript
674 | requestCustomGrant(config).then((response) => {
675 | console.log(response);
676 | }).catch((error) => {
677 | console.error(error);
678 | });
679 | ```
680 |
681 | ---
682 |
683 | ### updateConfig
684 |
685 | ```TypeScript
686 | updateConfig: (config: Partial) => Promise;
687 | ```
688 |
689 | #### Arguments
690 |
691 | 1. config: [`AuthClientConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#authclientconfigt) The config object containing the attributes that can be used to configure the SDK. To learn more about the available attributes, refer to [`AuthClientConfig`](https://github.com/asgardeo/asgardeo-auth-js-sdk#authclientconfigt) model.
692 |
693 | #### Description
694 |
695 | This method can be used to update the configurations passed into the `initialize` function. Please note that every attribute in the config object passed as the argument here is optional. Use this method if you want to update certain attributes after instantiation.
696 |
697 | #### Example
698 |
699 | ```TypeScript
700 | await updateConfig({
701 | signOutRedirectURL: "signOutRedirectURL"
702 | });
703 | ```
704 |
705 | ---
706 |
707 | ## Develop
708 |
709 | ### Prerequisites
710 | - [React Native Environment setup](https://reactnative.dev/docs/environment-setup)
711 |
712 | ## Contribute
713 |
714 | Please read [Contributing to the Code Base](http://wso2.github.io/) for details on our code of conduct, and the process for submitting pull requests to us.
715 |
716 | ### Reporting Issues
717 |
718 | We encourage you to report issues, improvements, and feature requests creating [Github Issues](https://github.com/asgardeo/asgardeo-react-native-oidc-sdk/issues).
719 |
720 | Important: And please be advised that security issues must be reported to security@wso2com, not as GitHub issues, in order to reach the proper audience. We strongly advise following the WSO2 Security Vulnerability Reporting Guidelines when reporting the security issues.
721 |
722 | ## License
723 |
724 | This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
725 |
--------------------------------------------------------------------------------