├── Facebook.js
├── Google.js
├── Navbar.js
├── Server.js
├── Style.js
├── cli.js
├── icons
├── ic_action_more.png
├── ic_action_more@2x.png
├── ic_action_more@3x.png
├── ic_action_refresh.png
├── ic_action_refresh@2x.png
├── ic_action_refresh@3x.png
├── ic_action_search.png
├── ic_action_search@2x.png
└── ic_action_search@3x.png
├── index.js
├── package.json
├── preview.gif
└── readme.md
/Facebook.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, {
4 | Component,
5 | StyleSheet,
6 | Text,
7 | View,
8 | WebView,
9 | ToastAndroid,
10 | AsyncStorage,
11 | Image,
12 | TouchableHighlight
13 | } from 'react-native';
14 |
15 | import api, {key, facebook} from './Server';
16 | import stylesheet from './Style';
17 |
18 | export default class extends Component {
19 | constructor(props) {
20 | super(props);
21 |
22 | this.state = {
23 | code: undefined,
24 | token: undefined,
25 | access: undefined,
26 | response: undefined,
27 | loading: false,
28 | };
29 | }
30 |
31 | render() {
32 | if (this.state.response) return this.renderResponse();
33 | if (this.state.access) return this.fetchProfile();
34 | if (this.state.token) return this.fetchAccess();
35 | if (this.state.code) return this.fetchToken();
36 |
37 | return this.renderScene();
38 | }
39 |
40 | renderScene() {
41 | return (
42 |
49 | );
50 | }
51 |
52 | renderResponse() {
53 | let profile = JSON.parse(this.state.response);
54 |
55 | return (
56 |
57 |
58 | {profile.name}
59 | this.onLogout()}>
63 | {this.state.loading ? `Please Wait . . .` : `Logout`}
64 |
65 |
66 | );
67 | }
68 |
69 | fetchToken() {
70 | if (this.state.token) return null;
71 |
72 | api.facebook.token(this.state.code)
73 | .then((response) => {
74 | if (!response.ok) throw Error(response.statusText || response._bodyText);
75 | return response.json()
76 | })
77 | .then((responseData) => {
78 | if (responseData && responseData.access_token) {
79 | this.setState({
80 | token: responseData.access_token
81 | });
82 | }
83 | })
84 | .catch((error) => {
85 | this.onError(error);
86 | })
87 | .done();
88 |
89 | return null;
90 | }
91 |
92 | fetchAccess() {
93 | if (this.state.access) return null;
94 |
95 | api.facebook.access(this.state.token)
96 | .then((response) => {
97 | if ((/access_token=/g).test(response._bodyText)) {
98 | this.setState({
99 | access: String(response._bodyText.split('&')[0]).replace('access_token=','')
100 | });
101 | }
102 | })
103 | .catch((error) => {
104 | this.onError(error);
105 | })
106 | .done();
107 |
108 | return null;
109 | }
110 |
111 | fetchProfile() {
112 | if (this.state.response) return null;
113 |
114 | api.facebook.profile(this.state.access)
115 | .then((response) => {
116 | if (!response.ok) throw Error(response.statusText || response._bodyText);
117 | return response.json()
118 | })
119 | .then((responseData) => {
120 | this.setState({
121 | response: JSON.stringify(responseData)
122 | });
123 | this.saveResponse().done();
124 | })
125 | .catch((error) => {
126 | this.onError(error);
127 | })
128 | .done();
129 |
130 | return null;
131 | }
132 |
133 | onNavigationStateChange(navState) {
134 | if ((/code=/g).test(String(navState.url))) {
135 | this.setState({
136 | code: String(navState.url).replace(`${facebook.redirect_uri}?code=`,'')
137 | });
138 | }
139 | }
140 |
141 | onLogout() {
142 | if (this.state.loading) {
143 | ToastAndroid.show(`Please Wait . . .`, ToastAndroid.SHORT);
144 | return null;
145 | }
146 |
147 | this.setState({loading: true});
148 |
149 | api.facebook.logout(this.state.access)
150 | .then((response) => {
151 | if (!response.ok) throw Error(response.statusText || response._bodyText);
152 |
153 | this.setState({
154 | code: undefined,
155 | token: undefined,
156 | access: undefined,
157 | response: undefined
158 | });
159 |
160 | this.removeResponse().done();
161 | })
162 | .catch((error) => {
163 | this.onError(error);
164 | })
165 | .done(() => {
166 | this.setState({loading: false});
167 | });
168 |
169 | return null;
170 | }
171 |
172 | onError(argument) {
173 | console.log(argument);
174 | ToastAndroid.show(String(argument).replace('Error: ',''), ToastAndroid.LONG);
175 | }
176 |
177 | async saveResponse() {
178 | try {
179 | await AsyncStorage.setItem(key, JSON.stringify(this.state.response));
180 | } catch (error) {
181 | this.onError(error);
182 | }
183 | }
184 |
185 | async removeResponse() {
186 | try {
187 | await AsyncStorage.removeItem(key);
188 | ToastAndroid.show(`Logout successfully!`, ToastAndroid.SHORT);
189 | } catch (error) {
190 | this.onError(error);
191 | }
192 | }
193 | }
194 |
195 | const styles = StyleSheet.create(stylesheet);
196 |
--------------------------------------------------------------------------------
/Google.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, {
4 | Component,
5 | StyleSheet,
6 | Text,
7 | View,
8 | WebView,
9 | ToastAndroid,
10 | TouchableHighlight,
11 | Image,
12 | AsyncStorage
13 | } from 'react-native';
14 |
15 | import api, {key, google} from './Server';
16 | import stylesheet from './Style';
17 |
18 | export default class extends Component {
19 | constructor(props) {
20 | super(props);
21 |
22 | this.state = {
23 | code: undefined,
24 | token: undefined,
25 | response: undefined,
26 | loading: false
27 | };
28 | }
29 |
30 | render() {
31 | if (this.state.response) return this.renderResponse();
32 | if (this.state.token) return this.fetchProfile();
33 | if (this.state.code) return this.fetchToken();
34 |
35 | return this.renderScene();
36 | }
37 |
38 | renderScene() {
39 | return (
40 |
47 | );
48 | }
49 |
50 | renderResponse() {
51 | let profile = JSON.parse(this.state.response);
52 |
53 | return (
54 |
55 |
56 | {profile.name}
57 | this.onLogout()}>
61 | {this.state.loading ? `Please Wait . . .` : `Logout`}
62 |
63 |
64 | );
65 | }
66 |
67 | fetchToken() {
68 | if (this.state.token) return null;
69 |
70 | api.google.token(this.state.code)
71 | .then((response) => {
72 | if (!response.ok) throw Error(response.statusText || response._bodyText);
73 | return response.json()
74 | })
75 | .then((responseData) => {
76 | if (responseData && responseData.access_token) {
77 | this.setState({
78 | token: responseData.access_token
79 | });
80 | }
81 | })
82 | .catch((error) => {
83 | this.onError(error);
84 | })
85 | .done();
86 |
87 | return null;
88 | }
89 |
90 | fetchProfile() {
91 | if (this.state.response) return null;
92 |
93 | api.google.profile(this.state.token)
94 | .then((response) => {
95 | if (!response.ok) throw Error(response.statusText || response._bodyText);
96 | return response.json()
97 | })
98 | .then((responseData) => {
99 | this.setState({
100 | response: JSON.stringify(responseData)
101 | });
102 | this.saveResponse().done();
103 | })
104 | .catch((error) => {
105 | this.onError(error);
106 | })
107 | .done();
108 |
109 | return null;
110 | }
111 |
112 | onNavigationStateChange(navState) {
113 | if ((/code=/g).test(String(navState.url))) {
114 | this.setState({
115 | code: String(navState.url).replace(`${google.redirect_uri}?code=`,'')
116 | });
117 | }
118 | }
119 |
120 | onLogout() {
121 | if (this.state.loading) {
122 | ToastAndroid.show(`Please Wait . . .`, ToastAndroid.SHORT);
123 | return null;
124 | }
125 |
126 | this.setState({loading: true});
127 |
128 | api.google.logout(this.state.token)
129 | .then((response) => {
130 | if (!response.ok) throw Error(response.statusText || response._bodyText);
131 |
132 | this.setState({
133 | code: undefined,
134 | token: undefined,
135 | response: undefined
136 | });
137 |
138 | this.removeResponse().done();
139 | })
140 | .catch((error) => {
141 | this.onError(error);
142 | })
143 | .done(() => {
144 | this.setState({loading: false});
145 | });
146 |
147 | return null;
148 | }
149 |
150 | onError(argument) {
151 | console.log(argument);
152 | ToastAndroid.show(String(argument).replace('Error: ',''), ToastAndroid.LONG);
153 | }
154 |
155 | async saveResponse() {
156 | try {
157 | await AsyncStorage.setItem(key, JSON.stringify(this.state.response));
158 | } catch (error) {
159 | this.onError(error);
160 | }
161 | }
162 |
163 | async removeResponse() {
164 | try {
165 | await AsyncStorage.removeItem(key);
166 | ToastAndroid.show(`Logout successfully!`, ToastAndroid.SHORT);
167 | } catch (error) {
168 | this.onError(error);
169 | }
170 | }
171 | }
172 |
173 | const styles = StyleSheet.create(stylesheet);
174 |
--------------------------------------------------------------------------------
/Navbar.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, {
4 | Component,
5 | StyleSheet,
6 | ToastAndroid,
7 | View,
8 | Text,
9 | TextInput,
10 | PropTypes
11 | } from 'react-native';
12 |
13 | import ToolbarAndroid from 'ToolbarAndroid';
14 |
15 | export default class extends Component {
16 | static propTypes = {
17 | onSearch: PropTypes.func,
18 | onRefresh: PropTypes.func
19 | };
20 |
21 | constructor(props) {
22 | super(props);
23 |
24 | this.state = {
25 | search: false,
26 | query: undefined
27 | };
28 | }
29 |
30 | render() {
31 | return (
32 |
33 |
38 | {this.state.search ? this.renderSearch() : this.renderTitle()}
39 |
40 |
41 | );
42 | }
43 |
44 | renderTitle() {
45 | return (
46 |
47 | {this.props.title}
48 |
49 | );
50 | }
51 |
52 | renderSearch() {
53 | return (
54 |
55 | this.state.query = text}
62 | onSubmitEditing={() => this.onSearch()}
63 | />
64 |
65 | );
66 | }
67 |
68 | onActionSelected(position) {
69 | switch (position) {
70 | case 0: this.onSearch(); break;
71 | case 1: this.onRefresh(); break;
72 | default: ToastAndroid.show(`${actions[position].title} selected.`, ToastAndroid.SHORT);
73 | }
74 | }
75 |
76 | onSearch() {
77 | this.props.onSearch && this.props.onSearch();
78 |
79 | if (this.state.query) ToastAndroid.show(`${this.state.query} not found`, ToastAndroid.SHORT);
80 | this.setState({search: !this.state.search, query: undefined});
81 | }
82 |
83 | onRefresh() {
84 | this.props.onRefresh && this.props.onRefresh();
85 | }
86 | }
87 |
88 | const icons = {
89 | more: require('./icons/ic_action_more.png'),
90 | search: require('./icons/ic_action_search.png'),
91 | refresh: require('./icons/ic_action_refresh.png'),
92 | };
93 |
94 | const actions = [
95 | {title: 'Search', icon: icons.search, show: 'always'},
96 | {title: 'Refresh', icon: icons.refresh, show: 'ifRoom'},
97 | {title: 'Single Sign On'},
98 | {title: 'Notifications'},
99 | ];
100 |
101 | const styles = StyleSheet.create({
102 | container: {
103 | flex: 1,
104 | alignItems: 'stretch',
105 | },
106 | toolbar: {
107 | height: 60,
108 | backgroundColor: '#00796B'
109 | },
110 | titleContainer: {
111 | flex: 1,
112 | justifyContent: 'center',
113 | backgroundColor: 'transparent',
114 | alignItems: 'center',
115 | },
116 | title: {
117 | alignSelf: 'flex-start',
118 | backgroundColor: 'transparent',
119 | fontSize: 20,
120 | color: '#ffffff'
121 | }
122 | });
123 |
--------------------------------------------------------------------------------
/Server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | export const key = '@lussatech:session';
4 |
5 | export const facebook = {
6 | client_id: '1505435769762540',
7 | client_secret: '210bdcf50efa27bc5bfc93b81a8b903d',
8 | oauth_dialog: 'https://www.facebook.com/dialog/oauth',
9 | redirect_uri: 'https://www.facebook.com/connect/login_success.html',
10 | oauth_token: 'https://graph.facebook.com/v2.3/oauth/access_token',
11 | oauth_access: 'https://graph.facebook.com/oauth/access_token',
12 | oauth_profile: 'https://graph.facebook.com/v2.5/me',
13 | oauth_logout: 'https://www.facebook.com/logout.php',
14 | };
15 |
16 | export const google = {
17 | client_id: '119869562795-rtsscilu9cb895r35dkokrvi6no9hvcd.apps.googleusercontent.com',
18 | client_secret: '87bg-4ElD3iUHI9kwR_Z1w2v',
19 | oauth_dialog: 'https://accounts.google.com/o/oauth2/v2/auth',
20 | redirect_uri: 'https://www.facebook.com/connect/login_success.html',
21 | oauth_token: 'https://www.googleapis.com/oauth2/v4/token',
22 | oauth_profile: 'https://www.googleapis.com/oauth2/v3/userinfo',
23 | oauth_logout: 'https://accounts.google.com/o/oauth2/revoke',
24 | };
25 |
26 | export default {
27 | facebook: {
28 | token: function (code) {
29 | let url = `${facebook.oauth_token}?client_id=${facebook.client_id}&client_secret=${facebook.client_secret}&redirect_uri=${facebook.redirect_uri}&code=${code}`,
30 | opt = {
31 | method: 'get'
32 | };
33 |
34 | return fetch(url, opt);
35 | },
36 | access: function (token) {
37 | let url = `${facebook.oauth_access}?grant_type=fb_exchange_token&client_id=${facebook.client_id}&client_secret=${facebook.client_secret}&fb_exchange_token=${token}`,
38 | opt = {
39 | method: 'get'
40 | };
41 |
42 | return fetch(url, opt);
43 | },
44 | profile: function (access) {
45 | let url = `${facebook.oauth_profile}?fields=id,name,email,about,age_range,picture&access_token=${access}`,
46 | opt = {
47 | method: 'get'
48 | };
49 |
50 | return fetch(url, opt);
51 | },
52 | logout: function (access) {
53 | let url = `${facebook.oauth_logout}?next=${facebook.redirect_uri}&access_token=${access}`,
54 | opt = {
55 | method: 'get'
56 | };
57 |
58 | return fetch(url, opt);
59 | },
60 | },
61 | google: {
62 | token: function (code) {
63 | let url = `${google.oauth_token}?grant_type=authorization_code&client_id=${google.client_id}&client_secret=${google.client_secret}&redirect_uri=${google.redirect_uri}&code=${code}`,
64 | opt = {
65 | method: 'post',
66 | headers: {
67 | 'Content-Type': 'application/x-www-form-urlencoded'
68 | }
69 | };
70 |
71 | return fetch(url, opt);
72 | },
73 | profile: function (token) {
74 | let url = `${google.oauth_profile}?alt=json&access_token=${token}`,
75 | opt = {
76 | method: 'get'
77 | };
78 |
79 | return fetch(url, opt);
80 | },
81 | logout: function (token) {
82 | let url = `${google.oauth_logout}?token=${token}`,
83 | opt = {
84 | method: 'get'
85 | };
86 |
87 | return fetch(url, opt);
88 | },
89 | }
90 | };
91 |
--------------------------------------------------------------------------------
/Style.js:
--------------------------------------------------------------------------------
1 | export default {
2 | container: {
3 | flex: 1,
4 | justifyContent: 'center',
5 | alignItems: 'center',
6 | },
7 | welcome: {
8 | fontSize: 17,
9 | textAlign: 'center',
10 | margin: 10,
11 | },
12 | instructions: {
13 | textAlign: 'center',
14 | color: '#333333',
15 | marginBottom: 5,
16 | },
17 | button: {
18 | padding: 15,
19 | margin: 20,
20 | justifyContent: 'center',
21 | alignSelf: 'stretch'
22 | },
23 | buttonActive: {
24 | backgroundColor: '#FFB300',
25 | },
26 | buttonDisabled: {
27 | backgroundColor: '#ffc300',
28 | },
29 | buttonText: {
30 | fontSize: 15,
31 | color: 'white',
32 | alignSelf: 'center'
33 | },
34 | image: {
35 | width: 200,
36 | height: 200
37 | }
38 | };
39 |
--------------------------------------------------------------------------------
/cli.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var fs = require('fs')
4 | , path = require('path')
5 | , source = path.resolve('node_modules', 'react-native-sso-authentication')
6 | , target = path.resolve(process.cwd(), 'lib')
7 | , ignore = ['cli.js', 'package.json', 'readme.md', 'preview.gif'];
8 |
9 | function run() {
10 | try {
11 | var packages = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), 'package.json'), 'utf8')) || undefined;
12 | } catch (e) {
13 | console.error('package.json couldn\'t be found, maybe `%s` is not the root of project directory', process.cwd());
14 | process.exit(1);
15 | } finally {
16 | var react = Object.keys(packages.dependencies).map(function (val) {
17 | if (val === 'react-native') return true;
18 | });
19 |
20 | if (react[0]) {
21 | writing(source, target);
22 | } else {
23 | console.error('react-native dependencies couldn\'t be found, maybe `%s` is not the root of react-native project directory', process.cwd());
24 | process.exit(1);
25 | }
26 | }
27 | }
28 |
29 | function writing(source, target) {
30 | if (!fs.existsSync(target)) {
31 | fs.mkdirSync(target);
32 | }
33 |
34 | copyFolderSync(source, target);
35 | }
36 |
37 | function copyFileSync(source, target) {
38 | var targetFile = target;
39 |
40 | if (ignore.indexOf(path.basename(source)) > -1) return;
41 |
42 | if(fs.existsSync(target)) {
43 | if(fs.lstatSync(target).isDirectory()) {
44 | targetFile = path.join(target, path.basename(source));
45 | }
46 | }
47 |
48 | fs.writeFileSync(targetFile, fs.readFileSync(source));
49 | }
50 |
51 | function copyFolderSync(source, target) {
52 | var files = [];
53 | var targetFolder = path.join(target, path.basename(source));
54 |
55 | if (!fs.existsSync(targetFolder)) {
56 | fs.mkdirSync(targetFolder);
57 | }
58 |
59 | if(fs.lstatSync(source).isDirectory()) {
60 | files = fs.readdirSync(source);
61 | files.forEach(function (file) {
62 | var curSource = path.join(source, file);
63 |
64 | if (fs.lstatSync(curSource).isDirectory()) {
65 | copyFolderSync(curSource, targetFolder);
66 | } else {
67 | copyFileSync(curSource, targetFolder);
68 | }
69 | });
70 | }
71 | }
72 |
73 | module.exports = {
74 | run: run
75 | };
76 |
--------------------------------------------------------------------------------
/icons/ic_action_more.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_more.png
--------------------------------------------------------------------------------
/icons/ic_action_more@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_more@2x.png
--------------------------------------------------------------------------------
/icons/ic_action_more@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_more@3x.png
--------------------------------------------------------------------------------
/icons/ic_action_refresh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_refresh.png
--------------------------------------------------------------------------------
/icons/ic_action_refresh@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_refresh@2x.png
--------------------------------------------------------------------------------
/icons/ic_action_refresh@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_refresh@3x.png
--------------------------------------------------------------------------------
/icons/ic_action_search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_search.png
--------------------------------------------------------------------------------
/icons/ic_action_search@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_search@2x.png
--------------------------------------------------------------------------------
/icons/ic_action_search@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/icons/ic_action_search@3x.png
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | import React, {
4 | AppRegistry,
5 | Component,
6 | StyleSheet,
7 | Text,
8 | View,
9 | TouchableHighlight,
10 | ScrollView,
11 | ToastAndroid
12 | } from 'react-native';
13 |
14 | import ToolbarAndroid from 'ToolbarAndroid';
15 |
16 | import Facebook from './Facebook';
17 | import Google from './Google';
18 | import Navbar from './Navbar';
19 | import Server, {key as Key, facebook as OAuthFacebook, google as OAuthGoogle} from './Server';
20 | import Style from './Style';
21 |
22 | export {Facebook, Google, Server, Key, OAuthFacebook, OAuthGoogle, Style};
23 |
24 | export default class extends Component {
25 | constructor(props) {
26 | super(props);
27 |
28 | this.state = {
29 | scene: undefined
30 | };
31 | }
32 |
33 | render() {
34 | return (
35 |
36 |
37 | this.setState({scene: undefined})} />
38 |
39 |
40 | {this.state.scene === 'facebook' ? this.renderFacebook() : this.state.scene === 'google' ? this.renderGoogle() : this.renderScene()}
41 |
42 |
43 | );
44 | }
45 |
46 | renderScene() {
47 | return (
48 |
49 | this.setState({scene: 'facebook'})}>
53 | {`Sign In with Facebook`}
54 |
55 | this.setState({scene: 'google'})}>
59 | {`Sign In with Google`}
60 |
61 |
62 | );
63 | }
64 |
65 | renderFacebook() {
66 | return ;
67 | }
68 |
69 | renderGoogle() {
70 | return ;
71 | }
72 | }
73 |
74 | const styles = StyleSheet.create({
75 | welcome: {
76 | fontSize: 20,
77 | textAlign: 'center',
78 | margin: 10,
79 | },
80 | instructions: {
81 | textAlign: 'center',
82 | color: '#333333',
83 | marginBottom: 5,
84 | },
85 | button: {
86 | height: 50,
87 | alignSelf: 'stretch',
88 | justifyContent: 'center',
89 | margin: 20,
90 | },
91 | buttonText: {
92 | fontSize: 18,
93 | color: 'white',
94 | alignSelf: 'center'
95 | },
96 | buttonFacebook: {
97 | backgroundColor: '#3A5795',
98 | },
99 | buttonGoogle: {
100 | backgroundColor: '#EA4335',
101 | },
102 | toolbarContainer: {
103 | flex: 1,
104 | alignItems: 'stretch',
105 | },
106 | toolbar: {
107 | height: 100,
108 | backgroundColor: '#00796B',
109 | },
110 | titleContainer: {
111 | flex: 1,
112 | justifyContent: 'center',
113 | backgroundColor: 'transparent',
114 | alignItems: 'center',
115 | marginRight: 34
116 | },
117 | title: {
118 | alignSelf: 'center',
119 | backgroundColor: 'transparent',
120 | fontWeight: 'bold',
121 | fontSize: 30,
122 | color: '#ffffff'
123 | }
124 | });
125 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-sso-authentication",
3 | "version": "1.0.3",
4 | "main": "index.js",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1"
7 | },
8 | "author": "Lussa Teknologi",
9 | "license": "ISC",
10 | "description": "a native sso authentication for react native",
11 | "repository": {
12 | "type": "git",
13 | "url": "https://github.com/lussatech/react-native-sso-authentication.git"
14 | },
15 | "bugs": {
16 | "url": "https://github.com/lussatech/react-native-sso-authentication/issues"
17 | },
18 | "homepage": "https://github.com/lussatech/react-native-sso-authentication"
19 | }
20 |
--------------------------------------------------------------------------------
/preview.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lussatech/react-native-sso-authentication/ffac046590b4261d869479e73b72e3665257b016/preview.gif
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | ### Installation
4 | npm i react-native-sso-authentication
5 |
6 | ### Generate Files
7 | Before generate library files to your react-native-project, make sure that `lussatech-cli` is installed globally in your machine, otherwise use this command to install it:
8 |
9 | npm i lussatech-cli -g
10 |
11 | If `lussatech-cli` have been installed, change directory to your react-native-project and run this command:
12 |
13 | lussatech generate react-native-sso-authentication
14 |
15 | then the library files will be added automatically inside your react-native-project, e.g.
16 |
17 | react-native-project
18 | |_ ...
19 | |_ lib
20 | |_ react-native-sso-authentication
21 | |_ ...
22 | |_ index.js
23 | |_ ...
24 |
25 | ### Usage
26 | ```javascript
27 | ...
28 | import SSOAuth, { // sample app
29 | /* available components */
30 | Navbar, // sample navigation bar
31 | Facebook, // sample facebook view
32 | Google, // sample google view
33 | /* available constants */
34 | Server, // sample api end-point
35 | Key, // sample key for asynstorage
36 | OAuthFacebook, // sample oauth facebook setting
37 | OAuthGoogle, // sample oauth google setting
38 | Style // sample styles
39 | } from './lib/react-native-sso-authentication';
40 |
41 | class Name extends Component {
42 | render() {
43 | return (
44 | // sample calling component
45 | );
46 | }
47 | }
48 | ...
49 | ```
50 |
51 | ###### Manage OAuth credentials
52 | To manage oauth credentials, update `Server.js` based on your oauth credentials, e.g.
53 |
54 | ```javascript
55 | # lib/react-native-sso-authentication/Server.js
56 |
57 | ...
58 | export const key = '@lussatech:session'; // key for asynstorage
59 | export const facebook = {
60 | client_id: '', // The id of your facebook app (Facebook App ID)
61 | client_secret: '', // The secret of your facebook app (Facebook App Secret)
62 | oauth_dialog: '', // The uri to display facebook login dialog
63 | redirect_uri: '', // The uri to capture response (code) from login dialog
64 | oauth_token: '', // The uri to exchange response (code) for an accessing token (short-lived-token)
65 | oauth_access: '', // The uri to exchange short-lived-token for long-lived-token
66 | oauth_profile: '', // The uri to get logged in user profile
67 | oauth_logout: '', // The uri to logged out user
68 | };
69 | export const google = {
70 | client_id: '', // The id of your google app (Google App ID)
71 | client_secret: '', // The secret of your google app (Google App Secret)
72 | oauth_dialog: '', // The uri to display google login dialog
73 | redirect_uri: '', // The uri to capture response (code) from login dialog
74 | oauth_token: '', // The uri to exchange response (code) for an accessing token
75 | oauth_profile: '', // The uri to get logged in user profile
76 | oauth_logout: '', // The uri to logged out user
77 | };
78 | ...
79 | ```
80 |
81 | ###### Customize navigation bar
82 | To customize navigation bar, update `Navbar.js` based on your need, e.g.
83 |
84 | ```javascript
85 | # lib/react-native-sso-authentication/Navbar.js
86 |
87 | ...
88 | export default class extends Component {
89 | /* to validate props value */
90 | static propTypes = {
91 | onRefresh: PropTypes.func,
92 | ...
93 | };
94 | ...
95 |
96 | /* when a menu is selected */
97 | onActionSelected(position) {
98 | switch (position) {
99 | case 0: this.onSearch(); break;
100 | case 1: this.onRefresh(); break;
101 | ...
102 | default: ToastAndroid.show(`${actions[position].title} selected.`, ToastAndroid.SHORT);
103 | }
104 | }
105 | ...
106 |
107 | /* when selected menu is `Refresh` */
108 | onRefresh() {
109 | /* calling onRefresh props action if available */
110 | this.props.onRefresh && this.props.onRefresh();
111 | }
112 | ...
113 | }
114 |
115 | /* list of menu */
116 | const actions = [
117 | {title: 'Search', icon: icons.search, show: 'always'},
118 | {title: 'Refresh', icon: icons.refresh, show: 'ifRoom'},
119 | ...
120 | ];
121 | ...
122 | ```
123 |
124 | #### Customize views
125 | To customize views, update `Facebook.js` and `Google.js` based on your need, e.g.
126 |
127 | ```javascript
128 | # lib/react-native-sso-authentication/Google.js
129 |
130 | ...
131 | render() {
132 | if (this.state.response) return this.renderResponse();
133 | if (this.state.token) return this.fetchProfile();
134 | if (this.state.code) return this.fetchToken();
135 |
136 | return this.renderScene();
137 | }
138 |
139 | renderScene() {
140 | return (
141 |
148 | );
149 | }
150 |
151 | renderResponse() {
152 | let profile = JSON.parse(this.state.response);
153 |
154 | return (
155 |
156 |
157 | {profile.name}
158 | this.onLogout()}>
162 | {this.state.loading ? `Please Wait . . .` : `Logout`}
163 |
164 |
165 | );
166 | }
167 | ...
168 | ```
169 |
--------------------------------------------------------------------------------