I am trying to create a flutter application using woocomerce API.
for that woocommerce i have created in my localhost
import 'dart:convert';
import 'dart:io';
import 'package:dio/dio.dart';
import 'package:ecommerce_store/config.dart';
import 'package:ecommerce_store/models/customer.dart';
class APIService {
Future<bool> createCustomer(CustomerModel model) async {
var authToken = base64.encode(
utf8.encode(Config.key + ":" + Config.sceret),
);
bool ret = false;
try {
var response = await Dio().post(
Config.url + Config.customerURL,
data: model.toJson(),
options: Options(headers: {
HttpHeaders.authorizationHeader: 'Basic $authToken',
HttpHeaders.contentTypeHeader: 'application/json'
}),
);
if (response.statusCode == 201) {
ret = true;
}
} on DioError catch (e) {
if (e.response?.statusCode == 401) {
ret = false;
} else {
ret = false;
}
// print(e);
}
return ret;
}
}
but when I try to do post-operation am getting
{
"code": "woocommerce_rest_cannot_view",
"message": "Sorry, you cannot list resources.",
"data": {
"status": 401
}
}
I saw that to access localhost API we need to use oauth1 but can anyone help me how to convert basic auth to oauth1
Thank you very much in advance
Related
I am trying to set up authentication for a project. Once a user signs up for our app they get sent to our home page with an id in the query. This id then gets used to submit user and then the jwt token gets saved inside redux state.
All our calls now go through an axios client where the jwt token is passed on every request. The token gets read with store.getState(injectStore)
This all works fine inside getserversideProps, but the issue comes in when using calls on the frontend that goes through NextJs built in 'pages/api' folder. Any calls inside those folders causes the store.getState() to be undefined. I do not understand why since it uses the exact same client as geserversideProps.
Example GetServersideProps(working)
try {
const response = await serverApiClient.get('v1/config');
return {
props: {
},
};
} catch ({ error: { statusCode = 500, message = 'Internal Server Error' } }) {
if (statusCode === 401) {
return {
redirect: {
permanent: false,
destination: '/',
},
};
}
throw new Error(message as string);
}
};
Example Frontend bff call(not working)
try {
// Call below get sent to next built in api
const players = await apiClient.get(`/defenders?sortBy=${statId}&team_id=${teamShortName}`);
return players;
} catch (error) {
return { error };
}
};
export default async function handler(req: NextApiRequest) {
console.log('Start request')
try {
const { sortBy, team_id: teamId } = req.query;
const response = await serverApiClient.get(`/v1/players/picks?position=DEF&sort_by=${sortBy}&team_id=${teamId}`);
Api Client
mergeConfigs(
params: Record<string, string>,
headers: Record<string, string>,
configs: Record<string, string>,
): AxiosRequestConfig {
const defaultConfigs = ApiClient.getDefaultConfigs();
*const token = store?.getState()?.jwtToken?.value*
//ISSUE ABOVE - This store .getState() is only undefined in nextJS api folder calls.
return {
...defaultConfigs,
...configs,
params,
headers: {
...defaultConfigs.headers,
...headers,
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
};
}
get(
uri: string,
params = {},
headers = {},
configs = {},
): Promise<AxiosResponse | any> {
return this.client
.get(uri, this.mergeConfigs(params, headers, configs))
.then((response) => {
return (response.data ? response.data : response);
})
.catch((error) => {
const errorObject = {
error: error?.response?.data,
};
throw Object.assign(errorObject);
});
}
If anyone has some advice on why that getStore is undefined in frontend-to-backend calls please assist. Thanks all!
This is my code in login api in next.js :
Login.js file -
import { magicAdmin } from "../../lib/magic";
import jwt from "jsonwebtoken";
export default async function login(req, res) {
if (req.method === "POST") {
try {
const auth = req.headers.authorization;
const didToken = auth ? auth.substr(7) : "";
console.log({ didToken });
const metadata = await magicAdmin.users.getMetadataByToken(didToken);
console.log({ metadata });
const token = jwt.sign(
{
...metadata,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000 + 7 * 24 * 60 * 60),
"https://hasura.io/jwt/claims": {
"x-hasura-allowed-roles": ["user", "admin"],
"x-hasura-default-role": "user",
"x-hasura-user-id": `${metadata.issuer}`,
},
},
"thisisasecretthisisasecret4445822"
);
console.log("generate", token);
res.send({ done: true });
} catch (error) {
console.error(error);
res.status(500).send({ done: false });
}
} else {
res.send({ done: false });
}
}
when i send POST request using thunderclient it is giving me this error :
{ didToken: 'token1' }
MagicAdminSDKError: Magic Admin SDK Error: [ERROR_MALFORMED_TOKEN] The DID token is malformed or failed to parse.
at new MagicAdminSDKError (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/core/sdk-exceptions.js:22:28)
at Object.createMalformedTokenError (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/core/sdk-exceptions.js:54:12)
at Object.parseDIDToken (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/utils/parse-didt.js:33:32)
at TokenModule.decode (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/modules/token/index.js:86:40)
at TokenModule.getIssuer (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/modules/token/index.js:95:21)
at UsersModule.<anonymous> (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/modules/users/index.js:137:41)
at step (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/modules/users/index.js:46:23)
at Object.next (/home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/modules/users/index.js:27:53)
at /home/jinalkhatri/Documents/Next Tutorials/netflix/node_modules/#magic-sdk/admin/dist/modules/users/index.js:21:71
at new Promise (<anonymous>) {
code: 'ERROR_MALFORMED_TOKEN',
data: []
}
i have added this as token in Bearer token field of Thunderclient :
token12wert
This is magic.js file :
import { Magic } from "#magic-sdk/admin";
export const magicAdmin = new Magic(process.env.NEXT_PUBLIC_MAGIC_SERVER_KEY);
The Bearer token which i was passing in the Thunderclient was wrong.
This is how i got the correct token :
import { magic } from "../../lib/magic-client";
const didToken = await magic.user.getIdToken();
console.log({didtoken});
and then passed this into the Thunderclient as Bearer Token, and it solved the issue.
In Flutter i try to get array in new firebase_messaging 10.0.0 like this
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:pushtest/functions/alert_messages.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:pushtest/constant/constant.dart' as Constants;
class PushNotifications {
FirebaseMessaging firebaseMessaging;
initNotifications() {
firebaseMessaging.requestPermission();
firebaseMessaging.getToken().then((token) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString('firebaseToken', token);
});
}
configuration(scaffold, location) {
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
var noti;
message as Map;
if (Platform.isIOS) {
noti = message['message'];
} else {
noti = message['data']['message'];
}
if (location == 'navigation') {
Messages.alert(scaffold.currentContext, noti);
} else {
Constants.message = noti;
}
return null;
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
var noti;
if (Platform.isIOS) {
noti = message['message'];
} else {
noti = message['data']['message'];
}
Constants.message = noti;
return null;
});
}
}
Problem: When i try to do
noti = message['message'];
Return
The operator '[]' isn't defined for the type 'RemoteMessage'. Try
defining the operator '[]'.
So what is the proper way to get array elements with listen functions?
If you are sending data messages then do:
noti = message.data['message'];
First, package.json :
"#angular/cli": "^6.0.8",
"rxjs": "6.2.1",
I am following a asp.net core 2 with angular tutorial. I had to adapt some code because it was thought for an older version.
The chapter is about creating JWT authentication.
I get the bearer token but when the api controller returns the response the auth.service gets an empty response and the line let token = res && res.token; goes false for the if so it never gets identified.
I suspect there is something wrong with the cast for TokenResponse but I cannot figure out what.
token.response.ts
interface TokenResponse {
token: string,
expiration: number
}
auth.service.ts
import { EventEmitter, Inject, Injectable, PLATFORM_ID } from "#angular/core";
import { isPlatformBrowser } from '#angular/common';
import { HttpClient, HttpHeaders } from "#angular/common/http";
import { Observable } from "rxjs";
import { map, catchError } from 'rxjs/operators';
import 'rxjs/Rx';
#Injectable()
export class AuthService {
authKey: string = "auth";
clientId: string = "NetCoreAngularWeb";
constructor(private http: HttpClient,
#Inject(PLATFORM_ID) private platformId: any) {
}
// performs the login
login(username: string, password: string): Observable<boolean> {
var url = "api/token/auth";
var data = {
username: username,
password: password,
client_id: this.clientId,
// required when signing up with username/password
grant_type: "password",
// space-separated list of scopes for which the token is
// issued
scope: "offline_access profile email"
};
return this.http.post<TokenResponse>(url, data)
.pipe(
map(res => {
let token = res && res.token;
// if the token is there, login has been successful
if (token) {
// store username and jwt token
this.setAuth(res);
// successful login
return true;
}
// failed login
return Observable.throw('Unauthorized');
}),
catchError(error => {
return new Observable<any>(error);
})
);
}
// performs the logout
logout(): boolean {
this.setAuth(null);
return true;
}
// Persist auth into localStorage or removes it if a NULL argument is given
setAuth(auth: TokenResponse | null): boolean {
if (isPlatformBrowser(this.platformId)) {
if (auth) {
localStorage.setItem(
this.authKey,
JSON.stringify(auth));
}
else {
localStorage.removeItem(this.authKey);
}
}
return true;
}
// Retrieves the auth JSON object (or NULL if none)
getAuth(): TokenResponse | null {
if (isPlatformBrowser(this.platformId)) {
var i = localStorage.getItem(this.authKey);
if (i) {
return JSON.parse(i);
}
}
return null;
}
// Returns TRUE if the user is logged in, FALSE otherwise.
isLoggedIn(): boolean {
if (isPlatformBrowser(this.platformId)) {
return localStorage.getItem(this.authKey) != null;
}
return false;
}
}
TokenController
[HttpPost("Auth")]
public async Task<IActionResult> Auth([FromBody]TokenRequestViewModel model)
{
// return a generic HTTP Status 500 (server Error)
// if the client payload is invalid.
if (model == null) return new StatusCodeResult(500);
switch (model.grant_type)
{
case "password":
return await GetToken(model);
default:
// not supported - return a HTTP 401 (Unauthorized)
return new UnauthorizedResult();
}
}
private async Task<IActionResult> GetToken(TokenRequestViewModel model)
{
try
{
// check if there's an user with the given username
var user = await UserManager.FindByNameAsync(model.username);
// fallback to support e-mail address instead of username
if (user == null && model.username.Contains("#"))
user = await UserManager.FindByEmailAsync(model.username);
if (user == null || !await UserManager.CheckPasswordAsync(user, model.password))
{
// user does not exists or password mismatch
return new UnauthorizedResult();
}
// username & password matches: create and return the Jwt token
DateTime now = DateTime.UtcNow;
// add the registered claims for JWT (RFC7519)
// For more info, see...
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(now).ToUnixTimeSeconds().ToString())
// TODO add additional claims here
};
var tokenExpirationMins = Configuration.GetValue<int>("Auth:Jwt:TokenExpirationInMinutes");
var issuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Auth:Jwt:Key"]));
var token = new JwtSecurityToken(
issuer: Configuration["Auth:Jwt:Issuer"],
audience: Configuration["Auth:Jwt:Audicnete"],
claims: claims,
notBefore: now,
expires:
now.Add(TimeSpan.FromMinutes(tokenExpirationMins)),
signingCredentials: new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256)
);
var encodedToken = new JwtSecurityTokenHandler().WriteToken(token);
// build & return the response
var response = new TokenResponseViewModel()
{
token = encodedToken,
expiration = tokenExpirationMins
};
return Json(response);
}
catch (Exception ex)
{
return new UnauthorizedResult();
}
}
EDIT - response, inspected with POSTMAN
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJlODBiNzRkMi0xOGIwLTQ5NzUtOWUyYS0wOGJiOGJlOTUzMDEiLCJqdGkiOiIzNTkzNjVhYS02M2UyLTQ3ZGMtYjY1NC1mMDk3YWQxNjNmMzQiLCJpYXQiOiIxNTMwNzEzMzU2IiwibmJmIjoxNTMwNzEzMzU2LCJleHAiOjE1MzU4OTczNTYsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzE3NzkvIn0.6QlGCK_4ybzYEz8qaRDDotOja6x0FI0fZTxmky94S5Y",
"expiration": 86400
}
Status 200 OK
Time:11281 ms
Size:671 B
Content-Type →application/json; charset=utf-8
Date →Wed, 04 Jul 2018 14:09:21 GMT
Server →Kestrel
Transfer-Encoding →chunked
X-Powered-By →ASP.NET
Well, there were a couple of issues here.
First, my version of Chrome was breaking the VS Studio Debugger. I had to update it to a 63+ Version (65 in my case)
https://social.msdn.microsoft.com/Forums/vstudio/en-US/5cd1aa58-d986-4d03-a10e-bf1fd62080a7/simultaneous-debugging-in-chrome?forum=vsdebug#5cd1aa58-d986-4d03-a10e-bf1fd62080a7
After this, I could debug better and I found the errors.
1- auth.service.ts . throwError function in Observable
https://www.academind.com/learn/javascript/rxjs-6-what-changed/
return this.http.post<TokenResponse>(url, data)
.pipe(
map(res => {
let token = res && res.token;
if (token) {
this.setAuth(res);
return true;
}
else {
//failed login
return Observable.throwError('Unauthorized');
}
}),
catchError(error => {
//console.log(error);
return new Observable<any>(error);
})
);
2- Typo error in TokenController Audiecnete instead of Audience
var token = new JwtSecurityToken(
issuer: Configuration["Auth:Jwt:Issuer"],
audience: Configuration["Auth:Jwt:Audience"],
claims: claims,
notBefore: now,
expires:
now.Add(TimeSpan.FromMinutes(tokenExpirationMins)),
signingCredentials: new SigningCredentials(issuerSigningKey, SecurityAlgorithms.HmacSha256)
);
I am using aurelia auth for login. But I can't get error message from server. In catch method err.response is undefined. Err is object with body of type Readable stream. Below is my code:
this.auth.login(bodyContent)
.then(response=>{
})
.catch(err=>{
console.log(err);
console.log(err.response);
});
in chrome developer tools I can see response message.
This is err printed:
I found solution here (https://gist.github.com/bryanrsmith/14caed2015b9c54e70c3) and it is the following:
.catch(error => error.json().then(serverError =>
console.log(serverError)
}));
The explanation can be found in the Aurelia docs:
The Fetch API has no convenient way of sending JSON in the body of a request. Objects must be manually serialized to JSON, and the Content-Type header set appropriately. aurelia-fetch-client includes a helper called json for this.
I also came across this same question recently.
I ended up creating a class called FetchError to encapsulate these sorts of errors. I then throw FetchError whenever an error occurs during a fetch.
login.ts:
import { FetchError } from '../../errors';
login() {
var credentials = { grant_type: "password", username: this.username, password: this.password };
return this.auth.login(credentials, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
.then((response) => {
return this.auth;
}).catch(err => {
this.errorMessage = "Login failed";
throw new FetchError("Unable to log in", err);
});
};
The FetchError class uses the 'http-status-codes' node module to look up the textual description.
errors.ts:
import * as HttpStatus from 'http-status-codes';
export class BaseError extends Error {
constructor(message) {
super(message);
this.message = message;
}
}
export class FetchError extends BaseError {
statusCode: number;
statusText: string;
description: string;
constructor(message: string, err: any) {
super(message);
if (err instanceof Response) {
var resp = <Response>err;
this.statusCode = resp.status;
if (resp.status == 12029)
this.statusText = "A connection to server could not be established";
else
this.statusText = HttpStatus.getStatusText(resp.status);
resp.json()
.then(body => {
this.description = body.Message;
console.log(`Error: ${this.message}, Status: ${this.statusText}, Code: ${this.statusCode}, Description: ${this.description}`);
})
}
else if (err instanceof Error) {
var error = <Error>error;
this.description = err.message;
console.log(`Error: ${this.message}, Description: ${this.description}`);
}
else {
this.description = "???";
console.log(`Unknown error: ${this.message}`);
}
}
}
I'm sure there are better ways of doing this. I'm still getting my head around this.