Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Support for Postman Authorization via API Key #52

Merged
merged 4 commits into from
Aug 26, 2024

Conversation

sl4wa
Copy link
Contributor

@sl4wa sl4wa commented Jul 13, 2024

Summary

This PR adds support for Postman API key authorization via a new console parameter --AuthHeader="header: value" or -A="header: value".

Changes

  • cli.ts: Added parsing for the new --AuthHeader (-A) parameter.
  • index.ts: Modified createPostmanCollection to accept API key header and value, handling the global authorization header separately and filtering it out from individual request headers.
  • format.ts: Updated queryCollectionToPostmanCollection and queryToItem to include the API key authorization block in the Postman collection and ensure the API key header is not added to individual items.
  • lib.ts: Refactored parseHeaders to handle the --AuthHeader (-A) parameter correctly, returning an array of [string, string] tuples.

Testing

  1. Run the CLI with the new --AuthHeader (-A) parameter.
  2. Verify that the generated Postman collection includes the API key authorization block at the root level and excludes the API key header from individual items.

Additional Notes

Please review the changes and let me know if any adjustments are needed.

@sl4wa sl4wa requested a review from nohehf as a code owner July 13, 2024 09:25
@nohehf
Copy link
Member

nohehf commented Jul 22, 2024

Hey there ! Thanks for the PR :)
Could you give more context / a specific use-case for why/when this extra flag is needed ? I feel like it is a bit mixed up with the "standard" headers (-H flag).
Thanks

@sl4wa
Copy link
Contributor Author

sl4wa commented Jul 22, 2024

Here is the use case.

Instead of having header being added to every HTTP request in the collection, Postman supports global level authorization.

For example by API Key.

image

This key will be added to the requests within the collection.

Copy link
Member

@nohehf nohehf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, that's what I thought thanks for the addition and suggestion.
After looking at the docs: https://learning.postman.com/docs/sending-requests/authorization/authorization-types/, it seems it could support most of the use cases so I think it's a nice addition.
I added some comments and suggestions, to harmonize it all. Graphman is quite an old codebase now, but I think it would be nice this way.
Sorry for the delay of my review, I had a lot of work lately :))
Also can you please add the flag usage to README.md?
Thank you!

src/cli.ts Outdated
combinedHeaders.push(args.Hapikey);
}

const headers = parseHeaders(combinedHeaders);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you want to mix the global header and regular ones, as I can see you later filter it out. Please juste parse and pass those separately

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

adding the combined header because they should be used in api call, right?

src/format.ts Outdated
}

function queryToItem(
query: FormattedQuery,
url: string,
headers?: Record<string, string>,
apiKeyHeader?: string,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you separate them as suggested, you can just remove it from this signature

src/format.ts Outdated
value,
})),
header: Object.entries(headers ?? {})
.filter(([key]) => key !== apiKeyHeader)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idem you won't need to filter it out

src/format.ts Outdated
@@ -83,17 +94,24 @@ export function queryCollectionToPostmanCollection(
queryCollection: QueryCollection,
url: string,
headers?: Record<string, string>,
) {
apiKeyHeader?: string,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the global header as a tuple[string,string]

src/format.ts Outdated
value: string;
type: string;
}[];
};
}

function queryToItem(
query: FormattedQuery,
url: string,
headers?: Record<string, string>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should change this type to Array<[string,string]>, and make it mandatory (it will just be empty if no headers).

src/index.ts Outdated
@@ -8,14 +8,24 @@ export { outrospect };
export async function createPostmanCollection(
url: string,
headers?: Record<string, string>,
apiKeyHeader?: string,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idem tuple here

src/lib.ts Outdated
`\n\nError parsing: \n ${h}. \n Please verify your headers.\n`,
);
}
export function parseHeaders(headers?: string[]): Record<string, string> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here you can return an array of tuples

src/cli.ts Outdated
const args = parse(Deno.args, {
boolean: ["help", "h"],
collect: ["H"],
string: ["Hapikey"],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the flag name is not really explicit, something like '--Global-Header', that may be shortened to '-GH', would be more explicit. Or maybe --AuthHeader?

@sl4wa sl4wa requested a review from nohehf July 27, 2024 08:23
@sl4wa
Copy link
Contributor Author

sl4wa commented Jul 27, 2024

Changes have been added, please review.

Copy link
Member

@nohehf nohehf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, maybe adding a -AH shorthand for the flag would be a nice addition

src/index.ts Outdated
const queryCollection = outrospectionToQueries(outrospection);
// Remove the authHeader from individual request headers
const headersWithoutAuth = headers.filter(([key]) => authHeader ? key !== authHeader[0] : true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to filter it out now that it is passed separately

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this filtering is to avoid confusion. If an Auth Header is present, we should not include the same Auth Header at the request level. It should only be included at the Postman collection level.

src/lib.ts Outdated
if (typeof header !== "string") {
throw new Error(`Header is not a string: ${header}`);
}
const [key, value] = header.split(": ", 2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to trim both the key and value, as it was before

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

src/lib.ts Outdated
}

async function query(
url: string,
query: string,
headers?: Record<string, string>,
headers?: Array<[string, string]>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be optional

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

@sl4wa
Copy link
Contributor Author

sl4wa commented Jul 30, 2024

An alias could be only one single character, so added -A as an alias for AuthHeader.
Please review.

@sl4wa sl4wa requested a review from nohehf July 30, 2024 06:39
@sl4wa sl4wa force-pushed the add-apikey-auth branch 4 times, most recently from e99a717 to 5c87222 Compare July 31, 2024 13:11
@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

Sorry I was of for about 3 weeks, and did not touch any computer
Getting back to work, let's merge this asap.

src/cli.ts Outdated
: undefined;

if (authHeader) {
headers.push(authHeader); // Add AuthHeader to headers for API access
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my last concern is this part, I don't get why you add the authHeader to the regular headers. This defeats the point of having it separate no ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's basically needed to get a response :)
these are the headers which are being passed by the tool to the API, not the headers from the collection

src/index.ts Outdated
const queryCollection = outrospectionToQueries(outrospection);
// Remove the authHeader from individual request headers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And this should not be needed at all

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

Hey @sl4wa, I just pushed a few changes to clean up some stuff, and simplify.
Let me know if this works for you, and i'll merge it once confirmed
Sorry again for the delay

@sl4wa
Copy link
Contributor Author

sl4wa commented Aug 26, 2024

Hi, i'm testing the changes. It does not work for me.

Seems that if we don't pass the new header along with the other HTTP headers it can't authorize.

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

Seems that if we don't pass the new header along with the other HTTP headers it can't authorize.

Then what's the point of having it globally as a separate parameter, if we duplicate it everywhere? If it is in the right place in the collection it should work. I believe something is missing in the collection generation part. Maybe the requests need to specify that they rely on the global header ?

@sl4wa
Copy link
Contributor Author

sl4wa commented Aug 26, 2024

You're right, there is no need to duplicate the header on the each postman's request level. It should be specified only once on the collection level.

But we still need to add this header to the requests that are being passed by this tool to get the schema. Ater the latest changes I'm not able to do that.

Error fetching introspection query.
 Please verify your URL, authorization, and network connection.

Once rolling back to commit from Jul 31, all works fine.

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

Once rolling back to commit from Jul 31, all works fine.

Yes but then it means that we duplicate the header, which defeats the hole point of this MR and can already be done via -H

Postman is currently having some issues: https://status.postman.com so I cannot test it.

If you can export a collection that has global authentication has you need it to json, I'll be happy to look into it, maybe:

    collection.auth = {
      type: "apikey",
      apikey: [
        { key: "in", value: "header", type: "string" },
        { key: "value", value: authHeader[1], type: "string" },
        { key: "key", value: authHeader[0], type: "string" },
      ],

is wrong.

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

But we still need to add this header to the requests that are being passed by this tool to get the schema. Ater the latest changes I'm not able to do that.

Oh okay that's why you merged it.
I'm going to pass this to the introspection request, and you should be good.

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

Passed the header to introspection too, without duplicating it everywhere

@sl4wa
Copy link
Contributor Author

sl4wa commented Aug 26, 2024

Passed the header to introspection too, without duplicating it everywhere

Thanks, it works good now!

With the latest changes the auth header is added to every Postman HTTP request. However I think we should filter it out and have it only at the collection level.

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

With the latest changes the auth header is added to every Postman HTTP request.

Oh that's my bad then, the goal was precisely not to do this yes. Looking into it

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

Fixed, was a little bug in my code (did not clone the header array so I was mutating it), should be all good

@sl4wa
Copy link
Contributor Author

sl4wa commented Aug 26, 2024

Thanks, it works perfectly fine now.

@nohehf
Copy link
Member

nohehf commented Aug 26, 2024

merging :)

@nohehf nohehf merged commit 2759def into Escape-Technologies:main Aug 26, 2024
2 checks passed
@sl4wa
Copy link
Contributor Author

sl4wa commented Aug 26, 2024

Thanks for approval.

I've noticed that in README we are specifying the v1.2.1 tag. This should probably be updated when you're ready.

@sl4wa sl4wa deleted the add-apikey-auth branch August 27, 2024 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants