Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a user authentication system for iOS (previously with Parse hopefully AWS) [closed]

Since Parse is going away, I had initially used their _User and PFUser implementation to create a user authentication process.

I have since begun switching to Amazon's AWS Mobilie Hub. I did notice in the Amazon Cognito system that they allow Google, Facebook, Amazon credential providers, which I don't want to use yet.

I go see the choice for a custom provider. Do I have to create my own backend auth system with a client and server side code for this to work?

Is there a simple way (but secure) login process for iOS like Parse had?

Thanks, any help would be appreciated (been reading a lot online).

like image 776
cdub Avatar asked Feb 01 '16 17:02

cdub


1 Answers

Yes, I use AWS Custom Authentication all the time.

Check this out and another answer I posted for custom authentication here

So the steps are:

  1. Set up Cognito to authenticate UNanthenticated users
    • You have to do this otherwise they won't be able to access anything before logging in. unauthenticated user

AND your authentic user Developer Name <- important part

developer name

  1. Set up DynamoDB (or whatever) to store your Username-Password information

  2. Go to IAM and make an AUTHENTICATED role and an UNAUTHENTICATED role.

  3. You give the UNAUTHENTICATED role, assign:

    AmazonCognitoDeveloperAuthenticatedIdentities AmazonDynamoDBFullAccess (if you want a Login & Register system) AmazonDynamoDBReadOnlyAccess (if you only want login)

IAM roles

  1. Also go in and do:

Edit Trust Relationship

{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Principal": {
            "Federated": "cognito-identity.amazonaws.com"
        },
        "Action": "sts:AssumeRoleWithWebIdentity",
        "Condition": {
            "StringEquals": {
                "cognito-identity.amazonaws.com:aud": "<YOUR_COG_ARN>"
            },
            "ForAnyValue:StringLike": {
                "cognito-identity.amazonaws.com:amr": "unauthenticated"
            }
        }
    }]
}
  1. Now make your AUTHENTICATED role, and assign:

    AmazonCognitoPowerUser AmazonDynamoDBFullAccess AmazonSNSFullAccess - for example, and whatever else you'd like

  2. Also go in and do:

Edit Trust Relationship

{
    "Version": "2012-10-17",
    "Statement": [{
        "Effect": "Allow",
        "Principal": {
            "Federated": "cognito-identity.amazonaws.com"
        },
        "Action": "sts:AssumeRoleWithWebIdentity",
        "Condition": {
            "StringEquals": {
                "cognito-identity.amazonaws.com:aud": "<YOUR_COG_ARN>"
            },
            "ForAnyValue:StringLike": {
                "cognito-identity.amazonaws.com:amr": "authenticated"
            }
        }
    }]
}

PLEASE NOTICE THE ONE CHANGE MADE - "authenticated" and "unauthenticated"

  1. Now this should be mobile hubs responsibility, but since they came out with that, everyone thinks they're relieved of responsibility! Not the case! You need to know what sts:AssumeRoleWithWebIdentity

  2. Now that you have everything set up, start your xcode project form Mobile Hub

  3. Fill in all the data (if its not there, which it should be because Mobile-Hub is nice to us) for your AUTHENTICATED ARN and your UNATHENTICATED ARN

  4. Set up your login page

  5. When the user goes to login, (encrypt their password) and send that and the username to DynamoDB.

12B. I really like using Lambda PARTICULARLY for mobile because you can really do a lot more AND you are less prone to errors AND you have more control, etc.

So with that said, go back to to step 4 & 6 IF you want to use Lambda and add and Inline Policy to the Roles. IAM -> Roles -> Your Role -> Create Role Policy And pop in:

{
    "Version": "2012-10-17",
    "Statement": [{
        "Sid": "",
        "Effect": "Allow",
        "Principal": {
            "Service": "lambda.amazonaws.com"
    },
    "Action": "sts:AssumeRole"
    }]
}

Now that you have the base set up, go back to Xcode.

  1. IF you are using Lambda, send in your username and password, let lambda pull the row from DynamoDB AND do the check on does the user exist, if so do the passwords match

Should look something like this in Lambda:

const
    AWS = require('aws-sdk'),
    ddb = new AWS.DynamoDB()

exports.handler = function(event, context) {
    var params = {
        TableName : '<users>',
        KeyConditionExpression : 'userType = :v_type AND username = :v_user',
        FilterExpression : 'password = :v_pass',
        ExpressionAttributeValues : {
            ':v_type' : { S : '<superdooper>' },
            ':v_user' : { S : event.username },
            ':v_pass' : { S : event.password }
        }
        //ProjectionExpression: 'email, joinDate, phone' (OPTIONAL)
    }
    ddb.query (params, function(err, data) {
        if (err) {
            context.fail (JSON.stringify(err, null, 2));
        } else {
            if (data.Count !== 0)
                context.succeed (data.Items);
            else
                context.succeed ('Wrong Info');
        }
    });
};

Once you get your data.Items back in Xcode, call this Lambda function, send in your variables, and when they say "good", call:

credentialsProvider.setLogins({developerAuthenticationProvider.getProviderName(), developerUserIdentifier});

Followed by credentialsProvider.refresh();

That part above should be in your Xcode project from MobileHub.

Now, this is were things get weird. There are a ton o` ways to do this. TVM, Cognito Assume Auth, server side, etc.

I always reassume authentication from Unauthenticated to Authenticated, but you have to do a lot of back end stuff if you want to get real analytics from both web side and mobile side if you're making this for both. But once you have your authenticated user, you now have a well authenticated user, ready to access whatever you listed in Step 6 as authenticated!

Hope this helps.

Update --- This is a dirty, unsafe, but fast way to do this. NOT FOR PRODUCTION.

In cognito, don't even make an Authenticated user role. Give your Unauthenticated user role all the permissions to do everything (DynamoDBFullAccess, S3FullAccess, EC2FullAccess, etc)

Then handle your authentication in the phone - Check the username and password against DynamoDB and then if it returns the information, set a variable to TRUE. This is not safe because the user now has access to all your stuff but it would look like this:

BOOL loggedIn = FALSE;
if (loggedIn) {
    [self loadView];
} else {
    [self loadLoginView];
}

- (void) loadLoginView {
    DynamoDBCall (username, password) withCompletion () {
        if (allGood) {
            _loggedIn = TRUE;
        }
    }
}
like image 179
iSkore Avatar answered Oct 02 '22 20:10

iSkore