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"
}
}
Related
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'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'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
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.
I am deploying a Next.js app using serverless component (serverless-next.js, not the plugin). After deploying, my API routes run smoothly, but some (not all) pages and all content in /public folder are not accessible.
On the web, requests to those resources end with a 503:
content-length: 1019
content-type: text/html
date: Tue, 27 Oct 2020 19:55:05 GMT
server: CloudFront
status: 503
via: 1.1 79ba346413d83ce62db11c8d0b05c22d.cloudfront.net (CloudFront)
x-amz-cf-id: RalFtcB6W4pm1_eTgzr0Y9LWCR-uwfqgW2alSgX_X72YVlUxlEkrKw==
x-amz-cf-pop: PRG50-C1
x-cache: LambdaExecutionError from cloudfront
I tracked down the error to Default Lambda#Edge for Next CloudFront distribution where I can see a record for every call in CloudWatch logs:
{
"errorType": "AccessDenied",
"errorMessage": "Access Denied",
"Code": "AccessDenied",
"RequestId": "75B8CCC0B1F960A7",
"HostId": "92cygvWjn3xLwT0PChJPc56ExzUFBDFTHyjLXQ/BWbT7pCVMb3I2ww15+Gzs2fSuXjHEPSfUIdg=",
"name": "AccessDenied",
"$fault": "client",
"$metadata": {
"httpStatusCode": 403,
"httpHeaders": {
"x-amz-request-id": "75B8CCC0B1F960A7",
"x-amz-id-2": "92cygvWjn3xLwT0PChJPc56ExzUFBDFTHyjLXQ/BWbT7pCVMb3I2ww15+Gzs2fSuXjHEPSfUIdg=",
"content-type": "application/xml",
"transfer-encoding": "chunked",
"date": "Tue, 27 Oct 2020 19:54:59 GMT",
"server": "AmazonS3"
},
"attempts": 1,
"totalRetryDelay": 0
},
"stack": [
"AccessDenied: Access Denied",
" at deserializeAws_restXmlGetObjectCommandError (/var/task/index.js:14166:41)",
" at processTicksAndRejections (internal/process/task_queues.js:97:5)"
]
}
I checked the origin S3 bucket and all resources are there. I tried to remove complete deployment and do a clean deploy to no avail. As I understand the problem lies in S3 permissions, I granted the policy under which the lambda is invoked full access to S3 but the problem persists.
Any help how to debug this further appreciated.
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.
I am attempting to use the Google JSON API - taskqueue/v1beta2
https://developers.google.com/apis-explorer/#p/taskqueue/v1beta2/taskqueue.tasks.list
I am not able to successfully authenticate for this service using the API explorer. I can use other JSON APIs like the storage API under the same project & account. When I go the the APIs tab in the developer console there is nothing listed for "TaskQueue" or "TaskQueue JSON API".
Edit: The oauth flow seems to work correctly, with scopes:
https://www.googleapis.com/auth/taskqueue
https://www.googleapis.com/auth/taskqueue.consumer
No matter what I do I get a 403 Forbidden response. How can I authorize my account to use the TaskQueue API? Here is my response from the API explorer:
403 Forbidden
cache-control: private, max-age=0
content-encoding: gzip
content-length: 146
content-type: application/json; charset=UTF-8
date: Mon, 19 Jan 2015 17:20:50 GMT
expires: Mon, 19 Jan 2015 17:20:50 GMT
server: GSE
vary: Origin, X-Origin
{
"error": {
"errors": [
{
"domain": "global",
"reason": "forbidden",
"message": "you are not allowed to make this api call"
}
],
"code": 403,
"message": "you are not allowed to make this api call"
}
}
The REST API only works for pull queues, and you need to also specify the email address of the user you are authorizing as in your queue.yaml. From the docs:
queue:
- name: pull-queue
mode: pull
acl:
- user_email: bar#foo.com # can list, get, lease, delete, and update tasks
- writer_email: user#gmail.com # can insert tasks
- writer_email: bar#foo.com # can insert tasks, in addition to rights granted by being a user_email above
Defining pull queues
https://cloud.google.com/appengine/docs/python/config/queue#Python_Defining_pull_queues