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.39k stars 2.11k forks source link

how to authenticate and use amplify sdk on my backend? #12944

Open Eliav2 opened 4 months ago

Eliav2 commented 4 months ago

Is this related to a new or existing framework?

React

Is this related to a new or existing API?

Authentication

Is this related to another service?

No response

Describe the feature you'd like to request

I've used amplify SDK on my backend to run scripts that interact with my backend directly (execute db migrations scripts, etc).

I've used amplify SDK on my backend because it directly simulates user interactions and handle much of the complexity, for example, when creating a record in a table, the createdAt,upadtedAt,id is automatically defined and GQL validations based on your schema takes place, while using DynamoDB SDK to change the DB does not go through validation and fields are not automatically populated.

So I have 2 questions to you guys:

My current method

which no longer works now, not sure why

// auth.ts
import { Amplify } from "aws-amplify";
import awsConfig from "../../src/aws-exports";
import {
  CredentialsAndIdentityId,
  CredentialsAndIdentityIdProvider,
  GetCredentialsOptions,
  getCurrentUser,
} from "aws-amplify/auth";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
import {
  AuthenticationDetails,
  CognitoUser,
  CognitoUserPool,
} from "amazon-cognito-identity-js";
import type { CognitoIdentityCredentials } from "@aws-sdk/credential-provider-cognito-identity/dist-types/fromCognitoIdentity";

const userPool = new CognitoUserPool({
  UserPoolId: awsConfig.aws_user_pools_id,
  ClientId: awsConfig.aws_user_pools_web_client_id,
});

const cognitoUser = new CognitoUser({
  Username: "<your-admin-email>", // replace with the user's username
  Pool: userPool,
});

const authenticationDetails = new AuthenticationDetails({
  Username: "<your-admin-userid>", // replace with the user's id from the user pool
  Password: "<your-admin-password>", // replace with the user's password
});

const getUserIdentityIdPromise = () =>
  new Promise<CognitoIdentityCredentials>((resolve, reject) => {
    cognitoUser.authenticateUser(authenticationDetails, {
      onSuccess: async function (result) {
        const logins = {} as any;
        logins[
          `cognito-idp.${awsConfig.aws_cognito_region}.amazonaws.com/${awsConfig.aws_user_pools_id}`
        ] = result.getIdToken().getJwtToken();

        const getCredentials = fromCognitoIdentityPool({
          clientConfig: { region: awsConfig.aws_cognito_region },
          identityPoolId: awsConfig.aws_cognito_identity_pool_id,
          logins: logins,
        }) as () => Promise<CognitoIdentityCredentials>;
        // return resolve(getCredentials);
        const credentials = await getCredentials();

        const identityId = credentials.identityId;

        resolve(credentials);
      },
      onFailure: function (err) {
        console.error(err);
        reject(err);
      },
    });
  });

const userCredentials = await getUserIdentityIdPromise();

class CustomCredentialsProvider implements CredentialsAndIdentityIdProvider {
  async getCredentialsAndIdentityId(
    getCredentialsOptions: GetCredentialsOptions,
  ): Promise<CredentialsAndIdentityId | undefined> {
    try {
      // const credentials = userCredentials
      const credentials: CredentialsAndIdentityId = {
        credentials: userCredentials,
        identityId: userCredentials.identityId,
      };
      return credentials;
    } catch (e) {
      console.log("Error getting credentials: ", e);
    }
  }

  // Implement this to clear any cached credentials and identityId. This can be called when signing out of the federation service.
  clearCredentialsAndIdentityId(): void {}
}

const customCredentialsProvider = new CustomCredentialsProvider();

Amplify.configure(awsConfig, {
  Auth: {
    // Supply the custom credentials provider to Amplify
    credentialsProvider: customCredentialsProvider,
  },
});

console.log("current user", await getCurrentUser()); // now throws error. used to work.

now each time I want to authenticate in a script that is making some useful operations i've simply imported the auth.ts file in the script:

// list-questions.ts
/**
 * list all questions from the database
 */
import "./auth.ts";
import { generateClient } from "aws-amplify/api";
import { listQuestions } from "../../src/graphql/queries.ts";

const client = generateClient();

const questions = await client.graphql({
  query: listQuestions.replaceAll("__typename", ""),
  variables: {
    limit: 1,
  },
});

console.log(questions);

this used to work like charm, and i could easily run script from my backend as if each operation executed by the script was executed by the mock admin user defined in the auth.ts file.

(consider enabling GitHub discussions for this repo to avoid 'issues' like that one)

Describe the solution you'd like

.

Describe alternatives you've considered

.

Additional context

No response

Is this something that you'd be interested in working on?

cwomack commented 4 months ago

Hey, @Eliav2 and thanks for opening up this issue. I'll mark it as a feature request for now and review it with our team internally, but have a question or two to clarify some context first. Are you trying to use Amplify exclusively on the server (with no intention to run on the client side/browser)? Do you have any user interaction on the client side at all? Thanks!

Eliav2 commented 4 months ago

Hey! Thanks for the response.

  1. Yes. My question is specifically about how to interact with amplify on the server. Interactions like gql queries.
  2. I do have user interactions on the client side. These interactions are normally authenticated and authorized by Cognito.

It could be great if amplify sdk could accept authentication on the server side by local aws cli profile with proper credentials (currently a cognito user with proper credentials must be supplied in the auth flow)

cwomack commented 4 months ago

@Eliav2, appreciate the clarity and reply! I'll review this feature request with the team and we'll update this issue with further questions or updates on progress as they come.