Issue logging into Azure B2C Angular application using #azure/msal-angular - msal

I'm having an odd error logging my app into B2C using auth code flow with PKCE using the #azure/msal-angular library. I'm redirecting back to the B2C login, get redirected back to my app, my app successfully gets a token back from the token api but then a JS error is logged and prevents my app from continuing to load. Here is the console output:
[Thu, 27 Jan 2022 22:34:53 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Info - Interceptor - 1 scopes found for endpoint
core.js:40853 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:handleRedirectStart
core.js:40853 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-angular#2.1.0 : Error - Interceptor - acquireTokenSilent rejected with error. Invoking interaction to resolve.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginStart
4msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginFailure
4core.js:6241 ERROR Error: Uncaught (in promise): BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
BrowserAuthError: interaction_in_progress: Interaction is currently in progress. Please ensure that this interaction has been completed before calling an interactive API. For more visit: aka.ms/msaljs/browser-errors.
at BrowserAuthError.AuthError [as constructor] (AuthError.js:27:1)
at new BrowserAuthError (BrowserAuthError.js:169:1)
at Function.push.../../node_modules/#azure/msal-browser/dist/error/BrowserAuthError.js.BrowserAuthError.createInteractionInProgressError (BrowserAuthError.js:236:1)
at RedirectClient.<anonymous> (StandardInteractionClient.js:216:51)
at step (_tslib.js:75:1)
at Object.next (_tslib.js:56:45)
at _tslib.js:49:1
at new ZoneAwarePromise (zone-evergreen.js:960:1)
at __awaiter (_tslib.js:45:1)
at RedirectClient.push.../../node_modules/#azure/msal-browser/dist/interaction_client/StandardInteractionClient.js.StandardInteractionClient.preflightInteractiveRequest (StandardInteractionClient.js:207:25)
at resolvePromise (zone-evergreen.js:798:1)
at zone-evergreen.js:705:1
at zone-evergreen.js:721:1
at ZoneDelegate.invoke (zone-evergreen.js:364:1)
at Object.onInvoke (core.js:41667:1)
at ZoneDelegate.invoke (zone-evergreen.js:363:1)
at Zone.run (zone-evergreen.js:123:1)
at zone-evergreen.js:857:1
at ZoneDelegate.invokeTask (zone-evergreen.js:399:1)
at Object.onInvokeTask (core.js:41645:1)
defaultErrorLogger # core.js:6241
handleError # core.js:6294
next # core.js:42627
schedulerFn # core.js:37132
__tryOrUnsub # Subscriber.js:183
next # Subscriber.js:122
_next # Subscriber.js:72
next # Subscriber.js:49
next # Subject.js:39
emit # core.js:37092
(anonymous) # core.js:41707
invoke # zone-evergreen.js:364
run # zone-evergreen.js:123
runOutsideAngular # core.js:41501
onHandleError # core.js:41704
handleError # zone-evergreen.js:368
runGuarded # zone-evergreen.js:136
api.microtaskDrainDone # zone-evergreen.js:670
drainMicroTaskQueue # zone-evergreen.js:576
Promise.then (async)
scheduleMicroTask # zone-evergreen.js:552
scheduleTask # zone-evergreen.js:388
onScheduleTask # zone-evergreen.js:272
scheduleTask # zone-evergreen.js:378
scheduleTask # zone-evergreen.js:210
scheduleMicroTask # zone-evergreen.js:230
scheduleResolveOrReject # zone-evergreen.js:847
resolvePromise # zone-evergreen.js:785
(anonymous) # zone-evergreen.js:705
webpackJsonpCallback # bootstrap:25
(anonymous) # mcl-portal-order.js:1
capture_page_info.js:954 Gather controls: 2.934814453125 ms
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : [64b25cee-dd82-4679-8a9e-b4eb65289ff3] : #azure/msal-common#6.0.0 : Info - in acquireToken call
DevTools failed to load source map: Could not load content for chrome-extension://lkoeejijapdihgbegpljiehpnlkadljb/browser-polyfill.js.map: HTTP error: status code 404, net::ERR_UNKNOWN_URL_SCHEME
client:52 [WDS] Live Reloading enabled.
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:loginSuccess
msal-config.module.ts:27 [Thu, 27 Jan 2022 22:34:54 GMT] : #azure/msal-browser#2.21.0 : Info - Emitting event: msal:handleRedirectEnd
If refresh my app after this happens the app loads fine and calls all my api endpoints appropriately using the token it got. So it's just the inital process of bootstraping my app, redirecting to the login, getting redirected back to my app, posting the token request then something fails inbetween the time the token is received but before the api requests are made?
Have I configured this wrong?
my MsalConfigModule that sets up the configuration of the MsalModule:
const isIE = window.navigator.userAgent.indexOf("MSIE ") > -1 || window.navigator.userAgent.indexOf("Trident/") > -1; // Remove this line to use Angular Universal
export function loggerCallback(logLevel: LogLevel, message: string) {
console.log(message);
}
export function MSALInstanceFactory(config: ConfigService): IPublicClientApplication {
const authConf = config.getSettings()['oauthConfig'][0] as any;
const authConfig = new PublicClientApplication({
auth: {
clientId: authConf['client_id'],
authority: authConf.authority,
knownAuthorities: [authConf.authority],
redirectUri: authConf['redirect_uri'],
postLogoutRedirectUri: authConf['redirect_uri'],
navigateToLoginRequestUrl: true
},
cache:{
cacheLocation: BrowserCacheLocation.SessionStorage,
storeAuthStateInCookie: isIE
},
system: {
loggerOptions: {
loggerCallback,
logLevel: LogLevel.Info,
piiLoggingEnabled: false
}
}
});
return authConfig;
}
export function MSALInterceptorConfigFactory(config: ConfigService): MsalInterceptorConfiguration {
const resourceMap = new Map<string, Array<string>>();
// iterate over the urlMappings config and create a protectedresourcemap
const configUrls = config.getSettings()['urlMappings'] as Array<any>;
const scope = config.getSettings()['oauthConfig'][0].scope as string;
configUrls.map(urlMap => resourceMap.set(`${urlMap.url}/*`, [scope]));
return {
interactionType: InteractionType.Redirect,
protectedResourceMap: resourceMap
};
}
export function MSALGuardConfigFactory(): MsalGuardConfiguration {
return {
interactionType: InteractionType.Redirect
};
}
#NgModule({
providers: [],
imports: [MsalModule]
})
export class MsalConfigModule {
static forRoot() {
return {
ngModule: MsalConfigModule,
providers: [
{
provide: MSAL_INSTANCE,
useFactory: MSALInstanceFactory,
deps: [ConfigService]
},
{
provide: MSAL_GUARD_CONFIG,
useFactory: MSALGuardConfigFactory,
deps: [ConfigService]
},
{
provide: MSAL_INTERCEPTOR_CONFIG,
useFactory: MSALInterceptorConfigFactory,
deps: [ConfigService]
},
MsalService,
MsalGuard,
MsalBroadcastService,
{
provide: HTTP_INTERCEPTORS,
useClass: MsalInterceptor,
multi: true
}
]
};
}
}
part of my main app module:
#NgModule({
declarations: [AppComponent],
imports: [
...
MsalConfigModule.forRoot()
],
providers: [
DatePipe,
SlicePipe
],
bootstrap: [AppComponent, MsalRedirectComponent],
})
export class AppModule {}

The solution to this was for me to add the
canActivate:[MsalGuard]
guard to all my routes. I think the underlying problem was that the interceptor was looking for a token to send in the api requests before we had a token to send. Adding the guard prevented the activation of the route until we are authenticated and then once the the route was activated my api requests would fire, the interceptors would have thier token to send along and everything just worked.
I guess the take way is that you do need to add the MsalGuard, it's not enough to provide the interceptors and configure the protected resource map.

Related

How to obtain a client secret in a teams toolkit project?

I'm working on a tab app where I intend using an on-behalf-of flow to obtain access token from azure active directory, so as to request data from Microsoft graph endpoints, and implementing this requires a client secret.
Is there a way I can get the client secret in a teams toolkit project just like I can get an application ID?
(Update) Details of what I'm trying to do
I'm working on an app where I would be calling Microsoft graph endpoints (protected by azure ad) to get data. The challenge I'm facing currently is how to handle authentication in a Teams tab app project created using Microsoft Teams Toolkit, so as to obtain an access token to request data from the graph endpoints or create an authenticated graph client.
What I have tried:
I have tried the code below, using the teamsfx.login() function within the react component where I'm calling a protected graph endpoint. But whenever I click the button to initiate a graph call, there is always a pop-up flash.
export const GraphEmail: React.FC = () => {
const [messages, setMessages] = useState<any[]>([]);
const handleGetMyMessagesOnClick = async (event: any): Promise<void> => {
await getMessages();
};
const getMessages = async (promptConsent: boolean = false): Promise<void> => {
const teamsfx = new TeamsFx();
await teamsfx.login(["User.Read", "Mail.Read"]);
const graphClient = createMicrosoftGraphClient(teamsfx, ["User.Read", "Mail.Read"]);
await graphClient
.api("/me/messages")
.select(["receivedDateTime", "subject"])
.top(15)
.get(async (error: any, rawMessages: any, rawResponse?: any) => {
if (!error) {
setMessages(rawMessages.value);
Promise.resolve();
} else {
console.error("graph error", error);
}
});
};
return (
<Flex column gap="gap.small">
<Header>Recent messages in current user&apos;s mailbox</Header>
<Button primary
content="Get My Messages"
onClick={handleGetMyMessagesOnClick}></Button>
<List selectable>
{
messages.map((message, i) => (
<List.Item key={i} media={<EmailIcon></EmailIcon>}
header={message.receivedDateTime}
content={message.subject} index={i}>
</List.Item>
))
}
</List>
</Flex>
);
}
In order to remove the consistent flash after the first popup for the actual login, since the user is already logged-in during the first button click, I made the changes below (idea gotten from the useGraph() component code on GitHub). But then I got an "uncaught (in promise) undefined" error when the button is clicked. The console logs are displayed below too.
export const NewGraphEmail: React.FC = () => {
const [needConsent, setNeedConsent] = useState(false);
const [messages, setMessages] = useState<any[]>([]);
const handleGetMyMessagesOnClick = async (event: any): Promise<void> => {
await getMessages();
};
const getMessages = async (promptConsent: boolean = false): Promise<void> => {
const teamsfx = new TeamsFx();
const scope = ["User.Read", "Mail.Read"];
if (needConsent) {
try {
await teamsfx.login(scope);
setNeedConsent(false);
// Important: tokens are stored in sessionStorage, read more here: https://aka.ms/teamsfx-session-storage-notice
} catch (err: unknown) {
if (err instanceof ErrorWithCode && err.message?.includes("CancelledByUser")) {
const helpLink = "https://aka.ms/teamsfx-auth-code-flow";
err.message +=
'\nIf you see "AADSTS50011: The reply URL specified in the request does not match the reply URLs configured for the application" ' +
"in the popup window, you may be using unmatched version for TeamsFx SDK (version >= 0.5.0) and Teams Toolkit (version < 3.3.0) or " +
`cli (version < 0.11.0). Please refer to the help link for how to fix the issue: ${helpLink}`;
}
throw err;
}
}
const graphClient = createMicrosoftGraphClient(teamsfx, scope);
await graphClient
.api("/me/messages")
.select(["receivedDateTime", "subject"])
.top(15)
.get(async (error: any, rawMessages: any, rawResponse?: any) => {
if (!error) {
setMessages(rawMessages.value);
Promise.resolve();
} else if (error instanceof GraphError && error.code?.includes("UiRequiredError")) {
// Silently fail for user didn't consent error
setNeedConsent(true);
// getMessages();
} else {
console.log("graph error", error);
}
});
};
return (
<Flex column gap="gap.small">
<Header>Recent messages in current user&apos;s mailbox</Header>
<Button primary
content="Get My Messages"
onClick={handleGetMyMessagesOnClick}></Button>
<List selectable>
{
messages.map((message, i) => (
<List.Item key={i} media={<EmailIcon></EmailIcon>}
header={message.receivedDateTime}
content={message.subject} index={i}>
</List.Item>
))
}
</List>
</Flex>
);
}
The logs in the browser console
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Info - Create
Microsoft Graph Client useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Info - Create
Microsoft Graph Authentication Provider with scopes: 'User.Read Mail.Read'
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Info - Get Graph
Access token with scopes: 'User.Read Mail.Read'
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Info - Create teams
user credential useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Verbose - Validate
authentication configuration
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Info - Get access
token with scopes: User.Read Mail.Read
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Verbose - Get SSO
token from memory cache
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:00 GMT] : #microsoft/teamsfx : Verbose - Failed to
call acquireTokenSilent. Reason: no_account_error: No account object
provided to acquireTokenSilent and no active account has been set. Please
call setActiveAccount or provide an account on the request..
authorize:74 BSSO Telemetry:
{"result":"Error","error":"NoExtension","type":"ChromeSsoTelemetry","data":
{},"traces":["BrowserSSO Initialized","Creating ChromeBrowserCore
provider","Sending message for method CreateProviderAsync","Received message
for method CreateProviderAsync","Error: ChromeBrowserCore error NoExtension:
Extension is not installed."]}
DevTools failed to load source map: Could not load content for
https://login.microsoftonline.com/5d2e66da-54ba-4897-82ee-
60eeb8ce5994/oauth2/v2.0/4616d84a89b332161726.map: HTTP error: status code
404, net::ERR_HTTP_RESPONSE_CODE_FAILURE
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:02 GMT] : #microsoft/teamsfx : Verbose - Failed to
call ssoSilent. Reason: login_required: AADSTS50058: A silent sign-in
request was sent but no user is signed in.
Trace ID: 5043daaa-b142-4083-9ad9-a798c2303b00
Correlation ID: ce16ec27-0261-423e-96f6-810344f76647
Timestamp: 2022-08-09 10:22:03Z.
useTeamsFx.js:34
[Tue, 09 Aug 2022 10:22:02 GMT] : #microsoft/teamsfx : Error - Failed to get
access token cache silently, please login first: you need login first before
get access token.
TestGraph.tsx:16
Uncaught (in promise) undefined
The uncaught error points to the end of the "handleGetMyMessagesOnClick" function above.
The other options:
The useGraph() hook: I would have loved to use the hook directly, but it seem to be suited for cases when using microsoft graph toolkit components, which won't serve my purpose during the project.
The on-behalf-of flow: I believe this would have solved the problem, following the steps in this video from the Microsoft 365 Developer channel, but the solution requires having an azure ad app client secret, which I don't know how to get in a microsoft teams toolkit project, since microsoft teams toolkit handles azure ad app registration.
A Client secret is a password to optain an access token though an API.
You need to implement an API than kan exchange an Teams SSO token, for a MS Graph API access token using a client secret (on-behalf-of). This client secret must never be exposed to the user/client, and should be secret; hence the name.
See this for a detailed explaination.
What you're wanting in this case is an "on behalf of" token from Graph, which lets you make calls to graph from your app as if it was the user ("on behalf of" the user) and it seems reasonable enough at first to do this in your client-side code. However, it turns out this isn't actually secure because it means the user's token is flying around almost in the open. As a result, it's better to create your own backend API (e.g. in an Azure Function) and make the "on behalf of" ("OBO") call from within there. Teams Toolkit actually creates some structure to help with this backend API, I think.
I'm not sure how well it covers Teams Toolkit (it's a while since I last watched it), but this video is an excellent overview: https://www.youtube.com/watch?v=kruUnaZgQaY . See here also for info: https://learn.microsoft.com/en-us/microsoftteams/platform/toolkit/visual-studio-code-tab-sso

Strip Resource from Request Path in AWS Lambda Proxy Integration

I have a lambda function and API gateway deployed through terraform. The API gateway has multiple resources under the top-level root resource / such as /first and /second. The resource for /first is set up with lambda-proxy integration (ANY and /first and ANY on /first/{proxy+}). The /second resource points to a different integration.
My lambda is an ASP.NET Core 3.1 with Lambda Custom Runtime generated initially with dotnet new serverless.AspNetCore30WebApi but later updated to 3.1 when support was added to AWS.
My issue is that when the lambda proxy integration transforms the request to be sent to the lambda function, it includes the full resource name (i.e. /first/Product instead of just /Product). Since my REST API in the lambda function only knows about Products and doesn't have a concept of what first is, I get 404 results for anything forwarded through the API gateway. I can't seem to find a place to strip the resource name from the path before it's forwarded on to the lambda function, because with the lambda proxy integration, it doesn't seem like you have a chance to do any request mapping templates or substitutions.
Thu Jun 03 12:24:52 UTC 2021 : HTTP Method: GET, Resource Path: /first/Product
Thu Jun 03 12:24:52 UTC 2021 : Method request path: {proxy=Product}
Thu Jun 03 12:24:52 UTC 2021 : Method request query string: {}
Thu Jun 03 12:24:52 UTC 2021 : Method request headers: {}
...
Thu Jun 03 12:24:52 UTC 2021 : Endpoint request body after transformations: <<relevant snippet parts formatted below>>
{
"resource": "/first/{proxy+}",
"path": "/first/Product",
"httpMethod": "GET",
"pathParameters": {
"proxy": "Product"
},
"requestContext": {
"resourcePath": "/first/{proxy+}",
"httpMethod": "GET",
"path": "/first/{proxy+}",
"protocol": "HTTP/1.1"
}
}

Apache HTTPAsyncClient closes connection before response

I am sending a GET request to an API using the Apache AsyncHTTPClient version 4.1.4 (latest). I can't seem to get a response from the server.
This is my request log.
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec generateRequest
FINE: [exchange: 2] Connection route established
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec generateRequest
FINE: [exchange: 2] Attempt 1 to execute request
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec generateRequest
FINE: [exchange: 2] Proxy auth state: UNCHALLENGED
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> GET /v1/contact?id=24 HTTP/1.1
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> Authorization: Bearer <token_removed>
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> Host: api.trial.ezyvet.com
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> Connection: Keep-Alive
Jun 04, 2020 3:40:01 PM org.apache.http.headers onRequestSubmitted
FINE: http-outgoing-1 >> User-Agent: Apache-HttpAsyncClient/4.1.4 (Java/11.0.6)
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.conn.ManagedNHttpClientConnectionImpl setEvent
FINE: http-outgoing-1 192.168.1.2:52932<->52.27.52.37:443[ACTIVE][rw:][ACTIVE][rw][NEED_UNWRAP][0][0][437]: Event set [w]
Jun 04, 2020 3:40:01 PM org.apache.http.impl.nio.client.MainClientExec requestCompleted
FINE: [exchange: 2] Request completed
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 14.622 s
When I send the same request using Postman, I get a successful response.
This is my code to handle the connection.
public void connect(HttpUriRequest request, FutureCallback<HttpResponse> callback) {
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
try {
sslContextBuilder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
try (CloseableHttpAsyncClient client = HttpAsyncClients.custom()
.setSSLContext(sslContextBuilder.build())
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build()) {
client.start();
client.execute(request, callback).get();
}
} catch (Exception e) {
Logger.getGlobal().severe("Couldn't execute the request using the AsyncClient.");
}
}
My debugger won't get triggered in any of the callback's methods (completed, failed, cancelled). Apparently the connection gets terminated for some reason.
Can someone explain what is happening here?
Thanks
I managed to solve this issue by changing the code to include a CountDownLatch instead of using client.execute(request, callback).get().
I passed down the latch to where the HttpResponse is read by JSON deserializer and count it down after everything completes.
This answer helped a lot.
https://stackoverflow.com/a/49359725/6663366

AWS Lambda: Can't access event['param'] via URL but it works on API GW Test

import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"headers": {"Content-Type": "application/json"},
"body": json.dumps(event['param'])
}
I'm not sure what I'm doing wrong. I succesfully setup API Gateway, a Python Lambda Function, proper DNS via Route53 and a valid TLS cert...
I can access my Lambda via calling mydomain.com/lambda but I'm not getting any params to pass through, only this error. Been trying for 5 frustrating hours now.
When called via mydomain.com/lambda
errorMessage "'param'"
errorType "KeyError"
stackTrace
0 " File \"/var/task/lambda_function.py\", line 7, in lambda_handler\n \"body\": json.dumps(event['param'])\n"
When called via API Gateway's "Test" (all good here)
Execution log for request
Tue Nov 05 22:42:47 UTC 2019 : Starting execution for request:
Tue Nov 05 22:42:47 UTC 2019 : HTTP Method: GET, Resource Path: /
Tue Nov 05 22:42:47 UTC 2019 : Method request path: {}
Tue Nov 05 22:42:47 UTC 2019 : Method request query string: {}
Tue Nov 05 22:42:47 UTC 2019 : Method request headers: {}
Tue Nov 05 22:42:47 UTC 2019 : Method request body before transformations:
Tue Nov 05 22:42:47 UTC 2019 : Endpoint request URI:
Tue Nov 05 22:42:47 UTC 2019 : Endpoint request headers: {x-amzn-lambda-integration-tag=Authorization=...[TRUNCATED]
Tue Nov 05 22:42:47 UTC 2019 : Endpoint request body after transformations:
{
"param" : "foo"
}
Tue Nov 05 22:42:47 UTC 2019 : Sending request to
Tue Nov 05 22:42:47 UTC 2019 : Received response. Status: 200, Integration latency: 36 ms
Tue Nov 05 22:42:47 UTC 2019 : Endpoint response headers: [...]
Tue Nov 05 22:42:47 UTC 2019 : Successfully completed execution
Tue Nov 05 22:42:47 UTC 2019 : Method completed with status: 200
And finally success (via API Gateway's "Test")
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "\"foo\""
}
How to get it working via URL? I try to actually get some header params from the client (browser) but step-by-step to learn. Seems I cannot even get anything to pass through from API Gateway to Lambda when called via URL, but why? What am I not getting here conceptually? :(
I set it all up correctly but didn't know that I had to re-deploy the API to make changes happen publicly.
That was the answer: Deploy the API again.

why "[web-server]: 404: /absoluteC" when running karma

I found several similar question but none of the suggestions fixed my issue. Basically they are suggesting add some dependency (I am using only native webcomponents so it doesn't appliy to my case) or check the path. I checked carefully and the path is 100% correct. I found a bit strange that the warnning message shows absolute before the real path. BTW, the path is really coorect.
Whole code github
Karma.conf.js
module.exports = function(config) {
config.set({
frameworks: ["jasmine"],
files: [
"../node_modules/#webcomponents/webcomponentsjs/webcomponents-bundle.js",
{ pattern: "../test/*-test.js", type: "module", included: true }
],
exclude: [],
preprocessors: {},
reporters: ["spec"],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ["Chrome"],
singleRun: true,
concurrency: Infinity
});
};
console message
# npm test
> sktscanner-flight-search#0.1.0 test C:\_d\WSs\rapidapi-vanilla-webcomponents\skyscanner-webcomponents
> karma start config/karma.conf.js
06 08 2019 19:22:55.229:INFO [karma-server]: Karma v4.2.0 server started at http://0.0.0.0:9876/
06 08 2019 19:22:55.251:INFO [launcher]: Launching browsers Chrome with concurrency unlimited
06 08 2019 19:22:55.261:INFO [launcher]: Starting browser Chrome
06 08 2019 19:22:58.972:INFO [Chrome 75.0.3770 (Windows 10.0.0)]: Connected on socket xwPc3314bVDtrBgaAAAA with id 78516319
06 08 2019 19:22:59.161:WARN [web-server]: 404: /absoluteC:/_d/WSs/rapidapi-vanilla-webcomponents/skyscanner-webcomponents/public/skyscanner-flight-search/skyscanner-flight-search.js
06 08 2019 19:22:59.165:WARN [web-server]: 404: /absoluteC:/_d/WSs/rapidapi-vanilla-webcomponents/skyscanner-webcomponents/test/test-utils.js
Chrome 75.0.3770 (Windows 10.0.0): Executed 0 of 0 ERROR (0.008 secs / 0 secs)
npm ERR! Test failed. See above for more details.
unit test
import { SkyscannerFlightSearch } from "../public/skyscanner-flight-search/skyscanner-flight-search.js";
import { TestUtils } from "./test-utils.js";
describe("simplest test", () => {
it("first try (using TestUtils)", async() => {
const { shadowRoot } = await TestUtils.render("skyscanner-flight-search");
expect(shadowRoot.querySelector("#firstdiv")).toBeTruthy();
});
});
Because Karma by default runs on port 9876, it doesn't have ability to look too deep into your project. Instead it hijacks your component and assumes everything is accessible from that port (which it is not)....
You can redirect Karma to your "real ports" using this guide

Resources