Integration of basic authentication to User Pool
Opened this issue · 11 comments
Hello,
How can I do a basic authentication (e.g. get access token) to a user pool on Cognito ?
All I was able to see in the repo was connections to Identity Providers (such as Facebook...).
Thanks!
It isn't supported in this. One user posted some code here that gave me a jump no connecting using user pools though.
It isn't clear what the roadmap is for proper AWS support of Cognito yet in react-native so for now the best hope imo is to cobble together bits from the ios and androis SDK's into react bridge code.
EDIT:
I misspoke I think...actually you can use the user pool as a cognito provider I think so the missing bit it authenticating against the pool using creds and fetching the idToken. The code linked above has example of that.
I am still trying to pull the pieces together myself but I think that is the right direction.
Ok I was able to use AWSRNCognitoCredentials with the CognitoUserPool backing.
A few things I needed to do for understanding this non-documented thing:
JS bug
The AWSCognitoCredentials.js
has a bug at line 48 which needs to be changed to:
listener.addListener("LoginsRequestedEvent", async ({callbackId}) => {
You might get some odd JSON errors from RCTConvert if you don't make this change. Basically the event raised from the native code is LoginRequestEvent
and that will send a payload of a NSDictionary that has something like { callbackId: <uuid> }
.
Workflow
First, you need to authenticate against the user pool and pull the idToken
out of the response. that is the missing thing in this sdk. The code I linked earlier can get a head start on that.
Once you have that, you need to use that token for using the federated identity flow.
When you call initWithOptions
here you can call setLogins
but only android needs that. What you need to be sure you provide is a getLogins
callback func that returns a JS map (object) where the key is the following format:
var logins = {}
logins[`cognito-idp.${REGION}.amazonaws.com/${USER_POOL_ID}`] = idTokenFromUserPool;
- If you try to use the
accessToken
you'll get a complain that it is missing theaud
claim, which makes sense ... the access token trims out some claims from identity token.
Checking it out
On IOS I made these calls and they worked once I figured out all that other junk:
const fetchedId = await AWSCognitoCredentials.getCredentialsAsync()
console.log('called getCredentialsAsync', fetchedId)
//this doesnt
console.log('calling getIdentityIDAsync')
const fetchedId2 = await AWSCognitoCredentials.getIdentityIDAsync()
console.log('called getIdentityIDAsync', fetchedId2)
I confirmed that my getLogins
callback was invoked as expected.
The getCredentialsAsync
got a response like:
{
"AccessKey": <hash>,
"Expiration": <datetime>,
"SecretKey": <hash>,
"SessionKey": <hash>
}
And the getIdentityIDAsync
got a response like:
{ identityId: "<region>:<uuid>" }
Deprecated usage of sendAppEventWithName
The SDK needs to be updated to subclass the RCTEventEmitter. See here for details on an approach for that.
It's unlikely this will be done here though so that looks like the next thing to solve...
HTH
I find this use case very basic.
The first thing every developer will try to implement is basic authentication(login/logout/sign in...)
@lielran the first drop of this SDK isnt concerned with the UserPool portion, but rather the Cognito Identity Provider side of the story which isnt concerned about login/logout.
I had to roll my own user pool stuff but once you have the id token you can use this sdk. Took me a while to recognize they are unrelated concerns (federation versus persona).
Hello,
I started to work back again on this recently. It seems that the easiest thing to do would be to get the id/access token using Native Bridge (I probably won't need the federation for now anyway).
As you said, @mnichols , this link is a great start.
I added the jars from the Android SDK and created the CognitoPackage implements ReactPackage
class as well. I was finally able to compile the project.
Unfortunately, at the very end, I could not load the module, the third does not recognize './Cognito'.
import { NativeModules } from 'react-native';
module.exports = NativeModules.ToastAndroid;
import Cognito from './Cognito';
I will post as soon as I am able to get the token; In the meantime, if anyone was able to make the native bridge working, I'd be glad to hear how to did it :)
@MathieuMailhos there is a missing bit in the Java stuff from that download. Follow the ReactNative docs for creating Native bridges for Android. Specifically make sure your MainActivity and MainApplication files have properly registered the module.
I've gotten pretty far along getting the android and ios sdks bound to ReactNative for user pool support but not quite ready. Their programming model isn't very friendly so reconsidering the approach.
Yes!
So I started to add the missing jars from the SDK:
$ ls android/app/libs/
aws-android-sdk-cognito-2.3.8.jar
aws-android-sdk-core-2.3.8.jar
aws-android-sdk-cognitoidentityprovider-2.3.8.jar
I updated MainApplication.java
with:
import com.rctcognito.RCTCognitoPackage;
// and later in the List<ReactPackage>
new RCTCognitoPackage(),
I created the folder in src/main/java/com/rctcognito
which includes:
AppHelper.java
Cognito.java (both from the AWS topic)
and RCTCognitoPackage.java, which is the Reat module:
package com.rctcognito;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class RCTCognitoPackage implements ReactPackage {
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules( ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new Cognito(reactContext));
return modules;
}
}
After all of that, I had a nicely compiling project (which means that package is well-loaded).
I Just had a problem to import it when doing:
import { NativeModules } from 'react-native';
module.exports = NativeModules.Cognito
import Cognito from './Cognito';
I have a big doubt about ./Cognito
syntax
@mnichols - I found it strange that the basic part is not supported(get a token) while the advanced is shown in the examples.
also, the solution above is valid for Android,right?
what about wrapping all aws apis via some v4 wrapper(e.g. https://github.com/leimd/react-native-aws-signature )
@mnichols I am trying to get the token from the user pool. I don't know where i have lost. I can't able to create a user in the pool(Users and groups). Kindly provide any sample code to get the token. I am following this link https://medium.com/@thexap/user-authentication-with-react-native-and-amazon-cognito-982cca085916