Angular 4 GET 403 response - django

I write an app in Angular 4 that calls a REST API (DJANGO).
The code is as followed:
export class ForecastUnitService {
private path = 'forecastunit/';
private options;
constructor (private http: Http, private c:CentralService) {
this.options=this.c.createOptions();
}
getForecastUnits(): Observable<ForecastUnit[]> {
return this.http.get(this.c.createURL(this.path),this.options)
.map(this.extractData)
.catch(this.handleError);
}
...
}
I add options that contains an authorization header, but still I get
a 403 forbidden. However when I try the call with cUrl or Postman or in swagger, with the same token I get results.
So first tought, the headers aren't correct but when I log options I get:
{"method":null,"headers":{"Authorization":["**Correct Token**"],"Content-Type":["application/json"]},"body":null,"url":null,"withCredentials":null,"responseType":null}
So that is not the problem, when I look in the response from Chrome I see the following:
{"detail":"Authentication credentials were not provided."}
So again no credentials, but I really passed them, what is going wrong?

Angular's http module changes all header names to lowercase. This might be an issue because some API services aren't following the spec and their header checks are case-sensitive when these should be case-insensitive.
Check the configuration of your API.
I assume that your CentralService creates valid options.
interface RequestOptionsArgs {
url: string|null
method: string|RequestMethod|null
search: string|URLSearchParams|{[key: string]: any | any[]}|null
params: string|URLSearchParams|{[key: string]: any | any[]}|null
headers: Headers|null
body: any
withCredentials: boolean|null
responseType: ResponseContentType|null
}
Headers:
class Headers {
static fromResponseHeaderString(headersString: string): Headers
constructor(headers?: Headers|{[name: string]: any}|null)
append(name: string, value: string): void
delete(name: string): void
forEach(fn: (values: string[], name: string|undefined, headers: Map<string, string[]>) => void): void
get(name: string): string|null
has(name: string): boolean
keys(): string[]
set(name: string, value: string|string[]): void
values(): string[][]
toJSON(): {[name: string]: any}
getAll(name: string): string[]|null
entries()
}

Could you show us the CentralService ?
Also you might want to avoid calling it in the constructor , instead implement OnInit

Related

add aws signature to the postman script using pm.sendRequest

I would like to use a postman pre-fetch script to refresh my app secret from an api protected by aws signature. I am able to make a basic authentication like this. However I need an aws signature authentication
var url = "https://some.endpoint"
var auth = {
type: 'basic',
basic: [
{ key: "username", value: "postman" },
{ key: "password", value: "secrets" }
]
};
var request = {
url: url,
method: "GET",
auth: auth
}
pm.sendRequest(request, function (err, res) {
const json = res.json() // Get JSON value from the response body
console.log(json)
});
hi just create a normal postman request that work properly and then copy that request to a variable by adding the below line in test script
pm.environment.set("awsrequest", pm.request)
Now you can use the awsrequest variable to send use in pm.sendRequest
pm.sendRequest(pm.environment.get("awsrequest"))

Loopback 4 OpenAPI connector: Specify Authorization header value per request

I have set up an OpenAPI connector in Loopback 4 as described here and for unauthorized requests, it is working well; I managed to create the respective datasource, service and controller. My service is similar to the GeocoderProvider example, but, let's say, with the following service interface.
export interface MyExternalService {
search_stuff(params: {query?: string}): Promise<MyExternalServiceResponse>;
}
export interface MyExternalServiceResponse {
text: string;
}
From my controller, I invoke it like this, where this.myExternalService is the injected service (kind of unrelated, but can Loopback also implicitly parse a JSON response from an external API datasource?):
#get('/search')
async searchStuff(#param.query.string('query') query: string): Promise<void> {
return JSON.parse(
(await this.myExternalService.search_stuff({query})).text,
);
}
Now, the external endpoint corresponding to myExternalService.search_stuff needs an Authorization: Bearer <token> header, where the token is sent to Loopback by the client, i.e. it's not a static API key or so. Assuming I added #param.query.string('token') token: string to the parameter list of my searchStuff controller method, how can I forward that token to the OpenAPI connector? This is the relevant part of the underlying OpenAPI YAML definition file:
paths:
/search:
get:
security:
- Authorization: []
responses:
'200':
content:
application/json:
schema:
$ref: '#/components/schemas/SearchResults'
operationId: search-stuff
components:
securitySchemes:
Authorization:
type: http
scheme: Bearer
I am now using the underlying execute function of the OpenAPI connector and manually intercept the request (the object that is passed to requestInterceptor is later passed directly to the http module by Swagger):
return JSON.parse(
(
await this.myExternalService.execute(
'search_stuff',
{query},
{
requestInterceptor: (req: {headers: {Authorization: string}}) => {
req.headers.Authorization = 'Bearer ' + token;
return req;
},
},
)
).text,
);
I also added the following method to the MyExternalService interface, inspired by the connector's actual execute function:
execute(
operationId: string,
parameters: object,
options: object,
): Promise<MyExternalServiceResponse>;
Some things I found:
Loopback internally uses the swagger-client module to do OpenAPI-based requests.
Specifically the securities option of Swagger's execute function expects a Security Definitions Object. There are some quirks with actually passing it to Swagger as well.
Internally, Swagger builds the final HTTP request that is sent out here in its source code. There, the securities key is mentioned, yet is is never actually used for the request. This means that manually specifying it in the third parameter of this.myExternalService.execute will change nothing.
I'll not accept this answer yet and I'm looking forward to finding a more Loopback-like approach.
I configured my service like this, to inject the basic authentication.
import {inject, lifeCycleObserver, LifeCycleObserver} from '#loopback/core';
import {juggler} from '#loopback/repository';
const SwaggerClient = require('swagger-client');
const config = {
name: 'jira',
connector: 'openapi',
spec: 'swagger-v2.json',
validate: false,
httpClient: (request: any) => {
request.headers["Authorization"] = "Basic " + Buffer.from("test:test").toString('base64');
return SwaggerClient.http(request);
},
};
#lifeCycleObserver('datasource')
export class JiraDataSource extends juggler.DataSource
implements LifeCycleObserver {
static dataSourceName = 'jira';
static readonly defaultConfig = config;
constructor(
#inject('datasources.config.jira', {optional: true})
dsConfig: object = config,
) {
super(dsConfig);
}
}

How do I restore the session ID for Express Session Authentication in a NativeScript app?

Buckle up, this one's a little bit complicated. I know that Express sends the browser a connect.sid cookie... and Passport uses this to deserialize the User on web requests. Not only that, but when I log in to my application from my NativeScript app (I'm running on a Pixel 2 emulator on a Windows PC, but I know it also works on iOS), the cookie seems to be correctly set and sent along with future web requests. I also understand how the application-settings API works, and that you can use this to store a user-identifying token for future boots of the application (so that I don't have to log in every time).
So here's where the disconnect occurs. Conceivably I can override the cookie in the request header if I have it stored, but nowhere can I find documentation on how to retrieve a cookie from the successful login request in nativescript.
Here's the code:
TokenSvc
import { Injectable } from "#angular/core";
import { getString, setString } from "application-settings";
export class TokenSvc {
static isLoggedIn(): boolean {
return !!getString("token");
}
static get token(): string {
return getString("token");
}
static set token(token: string) {
setString("token", token);
}
}
Login Component
(Note I am making an embarrassing attempt at getting the cookies from a new HttpHeaders instance... not sure why I thought that would work.)
#Component({
selector: "app-login",
moduleId: module.id,
templateUrl: "./login.component.html",
styleUrls: ["./login.component.scss"]
})
export class LoginComponent {
credentials: ILoginCredentials;
#ViewChild("password") password: ElementRef;
#ViewChild("handle") handle: ElementRef;
#ViewChild("confirmPassword") confirmPassword: ElementRef;
constructor(private page: Page, private router: Router, private AuthSvc: AuthSvc, private _store: Store<AppStore>) {
this.page.actionBarHidden = true;
this.credentials = {
email: "",
password: "",
cPassword: "",
handle: "",
publicName: ""
};
}
login() {
const loginCredentials: ICredentials = {
username: this.credentials.email,
password: this.credentials.password,
rememberMe: false
};
this.AuthSvc.login(loginCredentials).subscribe(
(payload) => {
console.log(payload);
if (payload.failure) {
alert(payload.failure);
} else {
// user!
let cookies = new HttpHeaders().get("Cookie");
console.log(cookies);
TokenSvc.token = cookies;
this._store.dispatch({ type: "SET_USER", payload: payload });
this.router.navigate(["/tabs"]);
}
}, () => alert("Unfortunately we were unable to create your account.")
);
}
}
The essential question here is... how do I persist a cookie-based session in NativeScript application-settings with a Node/Express back-end?
The essential answer is: you don't.
Prefer JWT, OAuth2 or any other token-based authentication method when it comes to mobile development. You can use the same authentication method for web too.
Store the user token using the secure storage and send the token along with any request made by the user.

Microsoft Cognitive services in swift 3

I am trying to use microsoft face recognition for my app. I have signed up for an account and started to implement into my app but cannot get any response except for 404 resource not found. Any ideas as to where I should start with this one?
import Foundation
import Alamofire
class CognitiveService {
static let instance = CognitiveService()
static let apiKey = API_KEY /// set in constants file
static let apiUrl = FACE_DETECT_URL /// set in constants file
func test() {
var header = [String : String]()
header["Ocp-Apim-Subscription-Key"] = CognitiveService.apiKey
let url = "any web address to image here"
let params:[String: String] = ["url": url]
let request = Alamofire.request(CognitiveService.apiUrl, parameters: params, headers: header)
print("\(request)")
request.responseJSON { (response) in
print(response)
}
}
}
Assuming FACE_DETECT_URL is set correctly, the issue is you're making a HTTP GET request (the default for Alamofire) when you wanted a POST. So you'll want:
let request = Alamofire.request(CognitiveService.apiUrl, method: .post, parameters: params, encoding: JSONEncoding.default, headers: header)

Akka-http: How to get custom header from a request?

I send following headers in a request to my akka-http api: "Content-type": "application/json", "Accept": "application/json", "AppId": "some_id".
How do I get "AppId" custom header in my akka-http route?
(get & parameters("id")) { (id) =>
complete {
val appId = ?? // I want to get custom header here.
}
}
Thanks.
You need to use one of the HeaderDirectives (HeaderDirectives docs) to extract the header. For example, if it's a custom one you can use headerValueByName which yields the value of the header, and rejects the route if the header was not present (if the header is optional you can use optionalHeaderValueByName):
headerValueByName("AppId") { appId =>
complete(s"The AppId was: $appId")
}
Happy hakking!
I actually prefer creating custom directive for things like authentication tokens, app ids and other parameters that are sort of mandatory for serving client's request. In your case it might look like this
val extractAppId = (headerValueByName("AppId") | headerValueByName("AppId2")).tflatMap[Tuple1[String]] {
case Tuple1(appId) =>
if (!appId.equalsIgnoreCase("BannedAppId"))
provide(appId)
else
complete(StatusCodes.Forbidden -> "Your application is banned")
}.recover {
case rejections => reject(ValidationRejection("AppId is not provided"))
}
which is used like
extractAppId { appId =>
get {
complete {
"Your AppId is " + appId
}
}
}
To make my example more interesting I added support of conditional response based on provided AppId.