Skip to content
This repository has been archived by the owner on Nov 25, 2020. It is now read-only.

api/orm are not utilizing aurelia-authentication fetch client #76

Closed
meash-nrel opened this issue Apr 14, 2016 · 26 comments
Closed

api/orm are not utilizing aurelia-authentication fetch client #76

meash-nrel opened this issue Apr 14, 2016 · 26 comments

Comments

@meash-nrel
Copy link

i'm using spoonx libs aurelia-authentication, aurelia-api, aurelia-orm. upgraded to the latest versions today.

regardless of the order the 3 plugins are loaded in aurelia configuration, the fetch request is not including the "authorization" header that aurelia-authentication injects. this results in all ORM calls returning only 401 Unauthorized due to this.

regular calls with aurelia fetch client are working fine as expected with aurelia-authentication "authorization" header.

@meash-nrel
Copy link
Author

it seems aurelia-authentication has a new base option that needs setting in it's configuration. must have appeared when aurelia-api started supporting >1 api endpoint.

    endpoint: 'api',             // use 'api' endpoint for auth
    configureEndpoints: ['api'],  // add Authorization header to endpoint calls

it all works fine now.

@RWOverdijk
Copy link
Member

@meash-nrel I like these issues the most, where the developer finds the answer even before I can help. Glad you found it! :)

@jrabalais
Copy link

@RWOverdijk How would I set this up if I am only using aurelia-api and not the ORM? My api is local, but I'm receiving 401 response. I did not have this issue with the standard configuration of the fetch client.

@doktordirk
Copy link
Contributor

Orm certainly isn.t needed. So, i don.t understand whats mit Working. Please post your Aurelia.api configuration and the api call

@meash-nrel
Copy link
Author

@jrabalais my answer above didn't involve ORM.

you have to set those config vars I posted above in the configuration you pass into aurelia-authentication. for me this is in a auth-config.js file that I pass into the plugin's .configure() call.

import authConfig from './_config/auth-config';
...
    aurelia.use
        ...
        .plugin('spoonx/aurelia-authentication', config => {
            config.configure(authConfig);
        })

@jrabalais
Copy link

OK, I'm not using aurelia-authentication either? Is that mandatory for the aurelia-api? My authentication is done in a login page prior to loading my aurelia app. This was not an issue with the fetch client.

Below is my main config:

`aurelia.use
.standardConfiguration()
.developmentLogging()
.plugin('aurelia-api', config => {
// Register hosts
config.registerEndpoint('api', '/api/');
})
.plugin('aurelia-kendoui-bridge', (kendo) => kendo.core());;

Below is my endpoint configuration. I'm getting a 401 on the endpoint.find method:

import {inject} from "aurelia-framework"; import {Endpoint} from "aurelia-api"; @inject(Endpoint.of('api')) export class CurrentUserFactory { constructor (endpoint) { this.endpoint = endpoint; } getUser() { return this.endpoint.find('currentuser') .then(response => { return response.json(); }); } }

@meash-nrel
Copy link
Author

Authentication is not required to use aurelia-api ... but it sure seems your API requires authentication as you are getting a 401 Unauthorized response...

"My authentication is done in a login page prior to loading my aurelia app. " -- so how is aurelia-api supposed to know the auth headers to include on the API call?

@jrabalais
Copy link

Yes, my API requires authentication, i think the useStandardConfiguration of the fetch-client handled that for me and configured my authentication from the browser. My project is an ASP.NET app that has a login page that redirects to a page hosting my aurelia client app.

@jrabalais
Copy link

This is what I had before and it worked fine.

import {inject} from "aurelia-framework";
import {HttpClient} from "aurelia-fetch-client";

let baseUrl = "/api/currentuser";

@Inject(HttpClient)
export class CurrentUserFactory {

constructor (httpClient) {
    httpClient.configure(config => {
        config
          .useStandardConfiguration()
    });
    this.http = httpClient;        
}

getUser() {
    return this.http.fetch(baseUrl)
                    .then(response => {
                        return response.json();
                    });
}

}

@jrabalais
Copy link

If aurelia-api is a wrapper around fetch-client, is there a way for me to configure the fetch client to useStandarConfiguration behind the scenes before I use aurelia-api?

@meash-nrel
Copy link
Author

yes. you can get an endpoint, then access it's .client property which is the fetch client. at the start of your app, you can modify it as you want - add interceptors, headers, whatever.

as an example, in my primary app.js i set up response error interceptor to globally handle 401s as a logged out event.

import {Config} from 'spoonx/aurelia-api';
...
@inject(Config)
export class App {
    constructor(apiConfig) {
        this.apiConfig = apiConfig;
    }
    activate() {
        let interceptor = {
            responseError(responseError) {
                // do something
            }
        };

        this.apiConfig.getEndpoint('api').client.interceptors.push(interceptor);
    }

@meash-nrel
Copy link
Author

basically API now contains a copy of it's own fetch client, one per endpoint, that it sets up in the plugin initialization. it no longer uses the global fetch client (how you did it before in your src example).

you can retrieve this fetch client per endpoint and modify it in the same way you did the global fetchConfig before, via getEndpoint().client in my example.

however your example src doesn't show how fetch was getting your auth headers from the ASP NET app... you need to inject them in the fetch client somehow.

@jrabalais
Copy link

That's what's confusing me I guess. I never did anything specific the get my auth headers from ASP.NET into fetch...it just worked. From what you're saying I should be able to do this:

this.apiConfig.getEndpoint('api').client.interceptors.useStandardConfiguration(); I'll try that and see if it works. Thanks so much for your help!

@jrabalais
Copy link

I tried both of these and neither worked:

constructor (endpoint) {
    endpoint.client.useStandardConfiguration();
    this.endpoint = endpoint;
}

constructor (endpoint) {
    endpoint.client.interceptors.useStandardConfiguration();
    this.endpoint = endpoint;
}

@doktordirk
Copy link
Contributor

@jrabalais you're making it way to complicated. some info here http://aurelia-authentication.spoonx.org/api_fetchConfig.html

  • you don't need to use aureli-api if you don't want.
  // This is the name of the endpoint used for any requests made in relation to authentication (login, logout, etc.). An empty string selects the default endpoint of aurelia-api.
  endpoint = null;
  // When authenticated, these endpoints will have the token added to the header of any requests (for authorization). Accepts an array of endpoint names. An empty string selects the default endpoint of aurelia-api.
  configureEndpoints = null;

so, just leave both empty and confiigure aurelia-fetch-client as you had before

however, you might wanna add the token to your request (that's the purpose of the plugin afterall)

the fetch config can do that for you
// this will add the interceptor for the Authorization header to the HttpClient singleton
this.fetchConfig.configure();

@doktordirk
Copy link
Contributor

above was for usage with out aurelia api. with api it's much easier as you only set those endpoints. that useDefaultConfiguration shouldn't be needed in that case. btw: the way useDefaultConfiguration is implemented it will reset your client and all previous setting is lost

@jrabalais
Copy link

But I'm not using aurelia-authentication at all in my project.

@doktordirk
Copy link
Contributor

ups

@doktordirk
Copy link
Contributor

doktordirk commented Jun 17, 2016

well, here's the doc for api http://aurelia-api.spoonx.org/

then like that it's the normal aurelia-fetch-client configure

    // 5: Own configuration
    config.registerEndpoint('auth', fetchconfigure => {
      fetchconfigure .withBaseUrl('https://api.aspnet.io/')
                         .useDefaultConfiguration();
    });

@doktordirk
Copy link
Contributor

doktordirk commented Jun 17, 2016

usage:

import {Config} from 'aurelia-api';

@inject(Config)
export class MyClass {
  constructor(config) {
    this.apiEndpoint = config.getEndpoint('auth');
this.client = this.apiEndpoint.client;

//and fetching a) using rest methods
 this.apiEndpoint .request(method, path[, body][, options])
    then(resultObject => ...

// or b) using fetch client directly
this.client.fetch(....

  }
}

@jrabalais
Copy link

@doktordirk Thank You! That's looks exactly like what I'm looking for. However, I just tried the below:

aurelia.use
  .standardConfiguration()
  .developmentLogging()
  .plugin('aurelia-api', config => {
      // Register hosts
      config.registerEndpoint('api', fetchconfigure => {
          fetchconfigure .withBaseUrl('/api/')
                             .useDefaultConfiguration()
      });        
  })
.plugin('aurelia-kendoui-bridge', (kendo) => kendo.core());;

And now I'm getting the below error:

main.js:11 Uncaught (in promise) TypeError: fetchconfigure.withBaseUrl(...).useDefaultConfiguration is not a function
at http://localhost:49849/dist/main.js:10:49
at HttpClient.configure (http://localhost:49849/jspm_packages/npm/aurelia-fetch-client@1.0.0-beta.2.0.1/aurelia-fetch-client.js:92:17)
at Config.registerEndpoint (http://localhost:49849/jspm_packages/npm/aurelia-api@3.0.0-rc4/aurelia-api.js:137:19)
at http://localhost:49849/dist/main.js:9:18
at r.configure (http://localhost:49849/jspm_packages/npm/aurelia-api@3.0.0-rc4/aurelia-api.js:196:5)
at http://localhost:49849/jspm_packages/npm/aurelia-framework@1.0.0-beta.1.2.4/aurelia-framework.js:276:36

@jrabalais
Copy link

Also, I didn't see your scenario in the api doc...where did I miss it?

@doktordirk
Copy link
Contributor

http://aurelia-api.spoonx.org/configuration.html
http://aurelia.io/docs.html#/aurelia/fetch-client/latest/doc/api/class/HttpClientConfiguration

was withDefault, resp useStandardConfiguration, my bad

      config.registerEndpoint('api', fetchconfigure => {
          fetchconfigure.withBaseUrl('/api/')
                               .useStandardConfiguration()

      });  

@jrabalais
Copy link

That did it! You have no idea how much I thank you...

@sysmat
Copy link

sysmat commented Sep 27, 2016

Is there no easy way to add HTTP Headers on the fly to the and point

@doktordirk
Copy link
Contributor

doktordirk commented Sep 27, 2016

interceptor can be added to do that. for always having it added. for always having it running one can

.plugin('aurelia-api', config => {
      // Register hosts
      config.registerEndpoint('api', 'api.com');

      // get client and add interceptor
     let fetchclient = config.getEndpoint('api').client;
     client.interceptor.push(myInterceptor);
  })

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants