I'm trying to use Google Identity platform api's with my firebase project ( I configured a payment method to use the identity platform sendOobCode and sendVerificationCode methods. But I keep receiving a 400 ERROR.
I tried using the built-in api calls in the console and got back more detailed errors.
"errors": [ { "message": "CONFIGURATION_NOT_FOUND", "domain": "global", "reason": "invalid" } ] }
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
var url = 'https://identitytoolkit.googleapis.com/v1/accounts:sendOobCode?key=[]';
var data = {
// requestType: "VERIFY_EMAIL",
idToken: userCredential._tokenResponse.idToken
}
console.log(userCredential)
axios.post(url, data, {
headers: {
'Content-Type': 'application/json'
}
}).then((res) => {
console.log(res)
}).catch((err) => {
console.log(err)
})
})
.catch((error) => {
.....
})
So I was able to get more information on my error by going into the Network Section in the dev tools. I checked the 400 request error and found in the response that I have an invalid API key. I forgot to remove the [] :)
Related
I am trying to attach an angular application to a .NET core API utilizing the JWT token. At this point i have the local angular app authenticating with Cognito and getting the user account.
I've followed this to get the token attached to the request.
https://medium.com/#umashankar.itn/aws-cognito-hosted-ui-with-angular-and-asp-net-core-5ddf351680a5
Amplify.Configure({
Auth: {
region: 'us-west-2',
userPoolId: 'us-west-MY POOL',
userPoolWebClientId: 'MY APP CLIENT ID'
}
}
});
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
if (request.url.indexOf(environment.api.baseUrl) == 0) {
return this.getToken().pipe(mergeMap(token => {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${token}`
}
});
return next.handle(request);
}));
}
return next.handle(request);
}
}
getToken() {
return from(
new Promise((resolve, reject) => {
Auth.currentSession()
.then((session) => {
if (!session.isValid()) {
resolve(null);
} else {
resolve(session.getIdToken().getJwtToken());
}
})
.catch(err => {
return resolve(null)
});
})
);
}
And i can confirm that it is adding the token to the request.
Interesting thing to note is that i'm using the session.getIdToken().getJwtToken() but there also is session.getAccessToken().getJwtToken() and they are different. I can't find anything telling me what the difference is, but i've tried both and they both have the same issue.
For the server side i've followed this answer to setup the .net core site and i can confirm that it is appropriately downloading the keys from /.well-known/jwks.json. It however just keeps rejecting the request with authentication failure.
How to validate AWS Cognito JWT in .NET Core Web API using .AddJwtBearer()
services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKeyResolver = (s, securityToken, identifier, parameters) =>
{
// get JsonWebKeySet from AWS
var json = new WebClient().DownloadString(parameters.ValidIssuer + "/.well-known/jwks.json");
// serialize the result
return JsonConvert.DeserializeObject<JsonWebKeySet>(json).Keys;
},
ValidateIssuer = true,
ValidIssuer = $"https://cognito-idp.us-west-2.amazonaws.com/us-west-MYID",
ValidateLifetime = true,
LifetimeValidator = (before, expires, token, param) => expires > DateTime.UtcNow,
ValidateAudience = true,
ValidAudience = "MY APP CLIENT ID"
};
});
app.UseAuthentication();
[HttpGet]
[Authorize]
public IEnumerable<Device> Get()
{
return 'my devices...';
}
The angular app is running at http://localhost:4200 and the .net core is running at https://localhost:44300.
So the question i have is, am i missing some sort of setup in my cognito app client? What am i missing to get the .NET core app to take the JWT?
Turns out i actually did have everything correct as far as Cognito goes.
What i did have was this.
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
Which is not the correct order for things to work... this is..
app.UseRouting();
app.UseAuthentication(); <-- Authentication before authorization
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
I got some troubles configuring an Hasura auth hook using a Lambda. I need such a function as I am storing my JWT token in an HTTP-only cookie, for security reasons.
I'm using a serverless function which returns a correct response (either when testing a curl request directly, or even when logging lambda):
{
"statusCode":200,
"body":"{\"X-Hasura-User-Id\":\"74d3bfa9-0983-4f09-be02-6a36888b382e\",\"X-Hasura-Role\":\"user\"}"
}
Yet, Hasura hook doesn't seem to recognize the response:
{
"type": "webhook-log",
"timestamp": "2020-02-07T10:27:34.844+0000",
"level": "info",
"detail": {
"response": null,
"url": "http://serverless:3000/auth",
"method": "GET",
"http_error": null,
"status_code": 200
}
}
These two lines of logs are adjacent in my logs. I just reformatted them a little bit to ease reading.
My lambda code looks like:
export const handler = async (event) => {
const cookies = getCookiesFromHeader(event.headers);
const { access_token: accessToken } = cookies;
let decodedToken = null;
try {
const cert = fs.readFileSync("./src/pem/dev.pem");
decodedToken = jwt.verify(accessToken, cert);
} catch (err) {
console.error(err);
return {
statusCode: 401,
};
}
const hasuraClaims = decodedToken['https://hasura.io/jwt/claims'];
return {
statusCode: 200,
body: JSON.stringify({
"X-Hasura-User-Id": hasuraClaims['x-hasura-user-id'],
"X-Hasura-Role": hasuraClaims['x-hasura-default-role']
})
}
}
Any idea on what is going on? Note that I'm using serverless offline, in case of. :)
In AWS Lambda, the spec requires the response body to be stringified and the actual response will be a parsed JSON object which is what Hasura will receive from the auth webhook.
When you are using serverless-offline, the response body is returned as a String (since JSON.stringify is used) without getting parsed. A simple curl will give you the difference.
The above code will work on Lambda but not on local development using serverless-offline. You will have to use the event object to see if isOffline is true and return JSON directly and if not return the stringified version.
Example code:
if(event.isOffline) {
// make it work with serverless-offline
return { "x-hasura-role": "user" ....};
} else {
// make it work with lambda
return { statusCode: 200, body: JSON.stringify({"x-hasura-role": "user"}) };
}
Official example in the serverless-offline repo along with error handling.
Related issues:
https://github.com/dherault/serverless-offline/issues/530
https://github.com/dherault/serverless-offline/issues/488
I'm using Pinpoint to push notifications through FCM and I'm receiving an error back from AWS:
{
"ApplicationId": "xxx",
"RequestId": "yyy",
"EndpointResult": {
"5551212": {
"DeliveryStatus": "PERMANENT_FAILURE",
"StatusCode": 410,
"StatusMessage": "{\"errorMessage\":\"Unregistered or expired token\",\"channelType\":\"GCM\",\"pushProviderStatusCode\":\"200\",\"pushProviderError\":\"InvalidRegistration\",\"pushProviderResponse\":\"{\\\"multicast_id\\\":752174934090126,\\\"success\\\":0,\\\"failure\\\":1,\\\"canonical_ids\\\":0,\\\"results\\\":[{\\\"error\\\":\\\"InvalidRegistration\\\"}]}\"}",
"Address": "userID"
}
}
An oddity is that when the app is launched/loaded the Amplify.config is not calling the PushNotification.onRegister function either:
const amplifyConfig = {
Auth: {
identityPoolId: POOL_ID,
region: 'us-east-1'
},
Analytics: {
AWSPinpoint: {
appId: APP_ID,
region: 'us-east-1',
mandatorySignIn: false,
endpointId: '5551212',
endpoint: {
address: 'userID',
channelType: 'GCM',
optOut: 'NONE'
}
}
}
}
PushNotification.onRegister(t => console.log(`Registration token: ${t}`), onRegister && onRegister());
PushNotification.onNotification(n => (console.log(n), onNotification && onNotification(n)));
PushNotification.onNotificationOpened(n => (console.log(n), onNotificationOpened && onNotificationOpened(n)));
Amplify.configure(amplifyConfig);
Edit: Your error seems related to Invalid Registration token: Make sure the endpoint address matches the registration token the client app receives from registering with FCM - https://developers.google.com/cloud-messaging/http-server-ref#error-codes).
I managed to make it work after login by getting the deviceToken from AsyncStorage.
If you want to keep the endpointId and only update the userId (only one user is logged in at each time - remember you can send push notifications to a specific userId that can have multiple endpoints (devices, email, phone number)):
try {
const deviceToken = await AsyncStorage.getItem('push_token'+aws_exports.aws_mobile_analytics_app_id)
if (deviceToken !== null) {
console.log('device token from AsyncStorage', deviceToken)
Analytics.updateEndpoint({
optOut: 'NONE',
channelType: 'GCM',
userId: userId,
address: deviceToken,
})
}
} catch (error) {
console.log('error retrieving device token from AsyncStorage', error)
}
OR, if you want to specify your own endpointId (this way you can have multiple users/endpoints in the same device):
try {
const deviceToken = await AsyncStorage.getItem('push_token'+aws_exports.aws_mobile_analytics_app_id)
if (deviceToken !== null) {
console.log('device token from AsyncStorage', deviceToken)
Analytics.configure({
disabled: false,
AWSPinpoint: {
appId: aws_exports.aws_mobile_analytics_app_id,
region: aws_exports.aws_mobile_analytics_app_region,
endpointId: endpointId,
endpoint: {
address: deviceToken,
channelType: 'GCM',
optOut: 'NONE',
userId: userId
}
}
})
Analytics.updateEndpoint({
optOut: 'NONE',
})
}
} catch (error) {
console.log('error retrieving device token from AsyncStorage', error)
}
First, check your debug messages using window.LOG_LEVEL='DEBUG'
Then, make sure Analytics is working! Configure the Analytics module before the Push Notification module (https://aws-amplify.github.io/docs/js/push-notifications#configure-your-app). Do you have a call to PushNotification.configure()?
As far as I know, you need to have PushNotification.onRegister() called to get a valid active targetable endpoint.
Are you testing in a real device?
And what happens if you don't set the endpointId and endpoint attributes on your amplifyConfig? It should update your endpoint address with the device token on its own. You can later on update your endpoint with the user id Analytics.updateEndpoint({optOut: 'NONE', UserId: 'xxx'})
ps.: I was having a related issue and now is finally working, but I set up my backend with Amplify CLI so it may be slightly different
Vue Js error (401 Unauthorized)
Vue Js Error: 401 Image
Software Used-
DRF
Vuejs
while calling DRF api in Vue js (using axios) unbale to get data.
below code in App.vue
export default {
name: 'App',
components: {
'Header': Header,
'Footer': Footer,
'Navbar': Navbar
},
data () {
return {
info: []
}
},
mounted () {
var self = this
axios.get('http://127.0.0.1:8000/management/api/list/')
.then(function (res) {
self.info = res.data
console.log('Data: ', res.data)
})
.catch(function (error) {
console.log('Error: ', error)
})
}
You are requesting to an API which is protected and need authorization credentials to be available.
If you are using DRF token-management systems, you should first get a token from proper API endpoint. then pass this token via Authorization header in request.
For example if you are using jwt token management system in django, then you should send requests like this:
axios.get('http://127.0.0.1:8000/management/api/list/', { Authorization: `jwt ${token}`})
.then(function (res) {
self.info = res.data
console.log('Data: ', res.data)
})
.catch(function (error) {
console.log('Error: ', error)
})
Remember it really depends on your Authentication backend you are using. So if you can give more details about how you implemented your django DRF APIs, I guess we all can help you much better.
Here I am trying to upload a video to user profile.
I have set up javascript sdk and my authentication works well .
I have the following code here..
FB.api(
`/${user_id}/videos`,
"POST",
{
"file_url": video,
"description": description,
"thumb": video_thumbnail,
"title": title,
},
function (response) {
console.log("fb response")
console.log(response)
if (response && !response.error) {
/* handle the result */
console.log("video upload response")
console.log(response)
}
});
Here I get the following error ..
code: 100
fbtrace_id: "FD5tVyrH9bS"
message: "(#100) Invalid format. It should be an image file data."
type: "OAuthException"
I am using file_url and passing url to my video. I guess it should upload the video..
Thank you for the response
I confirm that you must post image file data in source field when posting to Facebook.
You can test by use Postman.
This is example:
var fs = require("fs");
var request = require("request");
var options = { method: 'POST',
url: 'https://graph.facebook.com/v2.11/2011156779127713/thumbnails',
headers:
{ 'Postman-Token': '6c17c103-d8f6-47a5-713b-b3709dde762d',
'Cache-Control': 'no-cache',
'content-type': 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' },
formData:
{ access_token: 'test',
is_preferred: 'true',
source:
{ value: 'fs.createReadStream("./Downloads/923249_818835191462845_1528674847924045075_n.jpg")',
options:
{ filename: './Downloads/923249_818835191462845_1528674847924045075_n.jpg',
contentType: null } } } };
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});
The problem isn't the video or the URL, it's the thumb parameter.
The thumb parameter needs to be 'file data', not the URL.
As to what format the image needs to be in..please let me know if you find out! I'm asking the same here.
The facebook API is terrible...