aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.44k stars 2.13k forks source link

Cognito Without Amplify #3635

Closed lanbau closed 5 years ago

lanbau commented 5 years ago

Hi is it possible to use cognito without amplify?

There are some existing tutorials that use amazon-cognito-identity-js without amplify but it seems that it is deprecated.

manueliglesias commented 5 years ago

Hi @lanbau

It is possible but not recommended. Amplify will make it easier for you. Let us know if the docs at https://aws-amplify.github.io/ are helpful

As you mentioned, amazon-cognito-identity-js is deprecated (Amplify internally uses it though, but the plan is to change that)

lanbau commented 5 years ago

Hi @manueliglesias yes the docs are great and the React auth with 2 lines of code is awesome.

I do have some issues. Will file it in a new issue. Thanks manuel.

emonhaider commented 5 years ago

@manueliglesias is it a requirement to create the Cognito resource through Amplify (amplity auth add)? I have a an existing user pool that I want to leverage from an Angular app. How can I do that? Thanks!

ViggoV commented 5 years ago

But what if you want to use Cognito in a another setup, that isn't published to S3 and don't need any of the other resources that Amplify creates? We are migrating our K8S cluster to EKS and would like to explore the possibility of creating a shared Cognito User Pool across our product family. However, almost every resource I've found on Cognito promotes Amplify as the way to use it. Since Amplify is so opnionated it is definitely not the right tool for the job but I can't find a resource that can help me with a manual setup..

camilobern commented 5 years ago

The problem comes when you want to integrate Cognito with an existing application. We have an existing pipeline and existing user pools. Here we just want to be able to leverage Cognito as an IdP. Bringing in Amplify implied changing our deployment pipeline and recreating our existing user pool.

morgler commented 4 years ago

I also need Cognito WITHOUT Amplify. We tried to use Amplify and it only fits a very narrow kind of use cases. Cognito however can be used in many cases where Amplify fails or makes things more complicated. This is even true when starting a completely new application architecture. Please, please provide ways and documentation to use Cognito without Amplify!

jeffsheets commented 4 years ago

Has anyone found any AWS documentation for the Cognito API that AmplifyJS uses? I can't seem to find it posted anywhere. (EDIT: found the docs for the actions and errors here https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_Operations.html)

Watching the network tab, it appears that all calls are a POST against https://cognito-idp.us-east-2.amazonaws.com/ with the X-Amz-Target set to the desired action like AWSCognitoIdentityProviderService.InitiateAuth and AWSCognitoIdentityProviderService.RespondToAuthChallenge and various JSON body params.

I wonder if that endpoint is considered an internal AWS endpoint that could change without notice, or if that is a published endpoint that we could code against directly?

naticaceres commented 4 years ago

Thank you so much @jeffsheets that is exactly what I was looking for.

I am going to give it a shot, have you found anything else of use when trying to go around amplify for an authentication workflow with Cognito?

jeffsheets commented 4 years ago

@naticaceres I never did find anymore info on that API. For various reasons we ended up making our own serverside auth service and calling Cognito via the node js AWS.CognitoIdentityServiceProvider API https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CognitoIdentityServiceProvider.html

justin8 commented 4 years ago

Since this still comes up in search results often; what I believe most of you want is this: https://docs.amplify.aws/lib/auth/start/q/platform/js#re-use-existing-authentication-resource

You can use amplify as a library in your react app without needing to use amplify to create any of the backing resources.

short example code below for authing against a resource without creating any infrastructure with Amplify:

Run: yarn add aws-amplify (or npm/pnpm/whatever) to install the library to your frontend app

import Amplify from "aws-amplify";
import { AmplifySignOut, withAuthenticator } from "@aws-amplify/ui-react";
import * as config from "../aws-exports.json";

Amplify.configure({
  Auth: {
    region: config.userPoolRegion,
    userPoolId: config.userPoolId,
    userPoolWebClientId: config.userPoolWebClientId,
    identityPoolId: config.identityPoolID,
  },
  API: {
    endpoints: config.endpoints,
  },
});

const Main = () => {
  return (
    <div>
      <AppBar position="static">
        <Toolbar>
          <IconButton edge="start" color="inherit" aria-label="menu" href="#/">
            <Menu />
          </IconButton>

// Inside of your main app, add the sign in/out button with this:
          <AmplifySignOut />

        </Toolbar>
      </AppBar>
      <Router />
    </div>
  );
};

// Wrap your export so that it will require auth to access this page
export default withAuthenticator(Main);

In any page where you want to access an authenticated API (You need to set IAM permission mode on the API gateway; not Cognito User Pool; that is for JWT token auth instead):

import Amplify, { API, Auth } from "aws-amplify";

// Your app is configured from running the .Configure call higher up in your tree

API.get("api-one", "/path/to/resource").then((req, res) => { do_something(res) })

// The API returns just like a regular Axios call, and supports promises/async/await.
const data = API.post("api-two", "/path/to/another/resource");
console.log("Got back data:")
console.log(data)
this.setState({data})

// You can also access data about the identity like so:
const userInfo = await Auth.currentUserInfo()
const response = API.get("api-one", `/read/something/about/this/user/${userInfo.Id}`)

example aws-exports.json; this can be in-lined as well if you like, there's nothing special about the name/format here:

{
  "userPoolRegion": "ap-southeast-2",
  "userPoolId": "ap-southeast-2_xxxxxxxxx",
  "userPoolWebClientId": "xxxxxxx",
  "identityPoolID": "ap-southeast-2:xxxx-xxxx-xxxx-xxxx",
  "endpoints": [
    {
      "name": "api-one",
      "endpoint": "https://api-one.example.com",
      "region": "ap-southeast-2"
    },
    {
      "name": "api-two",
      "endpoint": "https://api-two.example.com",
      "region": "us-east-1"
    }
  ]
}

The region specified per-API must match the region of your API Gateway, this is the region that is used when signing the SigV4 auth request to your API, and it will only accept requests signed for the correct region.

morgler commented 4 years ago

Thanks for clarifying @justin8. Long ago I actually surrendered to using that solution. However, it feels wrong: I have to import the whole Amplify library although I do not want to use Amplify. Apart from the extra kB it also confuses developers, because it looks like we would use Amplify.

I would prefer a cleaner solution where CognitoJS is its own lean library. That way we could use it separately without the physical and mental bulk of Amplify; and Amplify could also include the CognitoJS library to package it with its build and management system.

chanlito commented 4 years ago

@morgler I'm looking to use cognito without amplify as well but google search keeps showing amplify which is very annoying. Have you found any resources?

morgler commented 4 years ago

Unfortunately no, @chanlito :(. To me it seems like Amazon tries to force developers into their half-baked Amplify library instead of selling Cognito separately. This is sad and makes me look for other solutions than Cognito (I used Firebase and Auth0 before, but they were both not production-ready back then). However, for the time being I have more important things on my plate and so I stick with adding Amplify only to use Cognito manually.

To be clear: I love the idea of Amplify, but after a lot of testing it simply isn't something I would use in production. I now use serverless. Once Amplify matures (i.e. breaks less often, is future-proof and allows manually configuration if needed), I will definitely consider it again. But even then: breaking out Cognito (and other AWS services) into separate libraries will be cleaner and more maintainable.

iamchathu commented 4 years ago

@morgler Agreed!

yh54321 commented 4 years ago

@morgler I see however that Cognito has a seemingly thorough documentation which does not reference Amplify https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-identity-pools.html. If I follow this guide, will I get stuck eventually...?

CaveSeal commented 4 years ago

Forgive me if I'm misunderstanding the issue, but can't you just install @aws-amplify/auth, and use the Auth class on its own?

import Auth from '@aws-amplify/auth'

Auth.configure({
    userPoolId: 'XX-XXXX-X_abcd1234',
    ...
})

https://aws-amplify.github.io/amplify-js/api/classes/authclass.html

yuyokk commented 4 years ago

@CaveSeal I second this! Did the same - setup Cognito via AWS Dashboard, installed @aws-amplify/auth and added Cognito resources manually to amplify setup. Works with no issues.

morgler commented 4 years ago

@CaveSeal thanks for this solution. The sample code I used actually had Amplify.configure(amplifyConfig) in it and I didn't know I could configure stuff directly on the Auth module! Thanks!

Now I just have to find a maintained VueJS lib for Cognito without Amplify in it or I will still be stuck with aws-amplify-vue.

ConnorJBishop commented 3 years ago

You could just use an odic client e.g oidc-client-js since Cognito is compliant with the spec, or at least most of it.

wesww commented 3 years ago

In case it helps anyone else who comes to this thread, I wanted to compare the code it would take to manually configure amplify (no CLI) vs to use the aws-sdk to do the same thing. Here's my full code for a request to fetch a file from a private S3 bucket using an IAM identity.

amplify

import Auth from '@aws-amplify/auth'
import Storage from '@aws-amplify/storage'

const region = 'us-east-1'
const identityPoolId = 'us-east-1:xxxx...'
Auth.configure({ region, identityPoolId })

const bucket = 'bucketname'
Storage.configure({
  AWSS3: { bucket, region }
})

Storage.get('s3keyname', { download: true })
  .then(result => console.log(result))
  .catch(err => console.log(err))

aws-sdk

import { S3Client, GetObjectCommand } from '@aws-sdk/client-s3'
import { CognitoIdentityClient } from '@aws-sdk/client-cognito-identity'
import { fromCognitoIdentityPool } from '@aws-sdk/credential-provider-cognito-identity'

const region = 'us-east-1'
const identityPoolId = 'us-east-1:xxxx...'
const client = new CognitoIdentityClient({ region })
const credentials = fromCognitoIdentityPool({ client, identityPoolId })
const s3Client = new S3Client({ region, credentials })

s3Client.send(new GetObjectCommand({
  Bucket: 'bucketname',
  Key: 'public/s3keyname'
})).then((data) => console.log(data))
.catch((err) => console.log(err))

https://gist.github.com/wesww/8760eff3aaa74b3a3bbbf6359673baf6

OndeVai commented 3 years ago

We are also interested in this. We are using just Amplify Auth js on the front end web. Even though they've made some improvements since 2018 related to tree shaking, it's still massively bloated. They are exporting massive javascript classes, so even the auth part is bloated as hell for us.

naticaceres commented 3 years ago

You guys, sorry for the long time, I was in fact able to leverage cognito without amplify for both angular and react. You need to use crypto JS and follow closely the cognito guidelines for Android. I've got a working stack blitz proof of concept, I'm not at home right now but it is public, I named it cognito without amplify or something like that, it should be in my github. I will try to clean it up and put it here sometime during next week.

lorenzocestaro commented 3 years ago

@ConnorJBishop got a thumbs down but the solution he proposed is valid. Cognito is an OIDC provider and will work with any library that implements the OIDC protocol. My team for example is using oidc-react. The downside is that, depending on your backend, you’ll probably have to write your authorization code. Another road that who doesn’t want to use amplify might try (n.b. I’ve not tried this so I’m not sure if it can actually work) is to use a library to sign your requests with aws v4 headers, for example aws4-axios which should be at the core of what Amplify does.

twfarland commented 3 years ago

I've been stuck with this too after get a bit nervous with Amplify storing id token in localStorage. The serverless stack site has some notes on a lower level alternative using signature v4 https://serverless-stack.com/chapters/connect-to-api-gateway-with-iam-auth.html - haven't worked through it yet though.

hadils commented 3 years ago

What is the status of using Cognito without AWS Amplify? I am doing server-side rendering in a JVM language, not Javascript. I don't want to use aws-amplify on my front-end. I would like a secure, RESTful solution. Any update is greatly appreciated.

Twipped commented 3 years ago

I too have landed here trying to find a solution. The aws-amplify library added nearly a whole MB of dependencies to our react build, and even when I paired down to just using @aws-amplify/auth it was still half a MB. That is a LOT of code when the only thing I want to do is handle third-party federated login.

github-actions[bot] commented 2 years ago

This issue has been automatically locked since there hasn't been any recent activity after it was closed. Please open a new issue for related bugs.

Looking for a help forum? We recommend joining the Amplify Community Discord server *-help channels or Discussions for those types of questions.