Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix removing cookie when topLevelDomain is used #67

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,25 @@ namespace app.guest.login {
}
```

## Cookies

Cookies are helpful for adding the authentication token to external, non angular, requests to an API. For example, if
you have an `<img>` tag that references a dynamic image on the API that requires authentication. The browser can add
the token in a cookie when making the image request.

To enable cookies set `config.cookie.enabled = true`.

You can optionally allow the cookie to be used for requests on other subdomains. This is useful if your webapp is on
one subdomain but your API is on a different subdomain.

angular-jwt-auth can automatically find the top level domain (like `example.com`) or you can provide a specific domain
name. Note that your domain must be the top level domain (or a subdomain) of the location in the browser URL.

To enable automatic top level domain detection set `config.cookie.topLevelDomain = true`.

To set a specific top level domain name set `config.cookie.topLevelDomainName = "your.domain.name"`


## Todo
* Better documentation with examples in typescript.
* Site hosted on github showing off examples with material
11 changes: 9 additions & 2 deletions src/fixtures.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,15 @@ export function cookiesFactoryMock(allowDomain:string) {
return cookieStore[key];
},

remove: (key) => {
delete cookieStore[key];
remove: (key, conf) => {
let cookie = cookieStore[key];
if (cookie && cookie.conf && cookie.conf.domain) {
if (conf && conf.domain && conf.domain === cookie.conf.domain) {
delete cookieStore[key];
}
} else {
delete cookieStore[key];
}
}
};
};
Expand Down
1 change: 1 addition & 0 deletions src/ngJwtAuthInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export interface ICookieConfig {
enabled:boolean;
name?:string;
topLevelDomain?:boolean;
topLevelDomainName?:string;
}

export interface INgJwtAuthServiceConfig {
Expand Down
1 change: 1 addition & 0 deletions src/provider/ngJwtAuthServiceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export class NgJwtAuthServiceProvider implements ng.IServiceProvider {
enabled: false,
name: 'ngJwtAuthToken',
topLevelDomain: false,
topLevelDomainName: null,
}
};

Expand Down
13 changes: 10 additions & 3 deletions src/service/ngJwtAuthService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -856,7 +856,7 @@ describe('Service tests', () => {

});

it('should be able to configure the cookie to be saved to the top level domain', () => {
it('should be able to configure the cookie to be saved to the top level domain and remove when logging out', () => {

expect(config.cookie.enabled).to.be.true; //check the service is configured to save cookies

Expand All @@ -872,12 +872,19 @@ describe('Service tests', () => {

$httpBackend.flush();

let cookie = $cookies.get(config.cookie.name);
let cookieExists = $cookies.get(config.cookie.name);

let cookieObject = $cookies.getObject(config.cookie.name);

expect(cookie).to.equal(token);
expect(cookieExists).to.equal(token);
expect(cookieObject.conf.domain).to.equal(cookieDomain);
expect(cookieObject.conf.expires).to.be.instanceOf(Date);

ngJwtAuthService.logout(); //logout

let cookieMissing = $cookies.get(config.cookie.name);

expect(cookieMissing).to.be.undefined;

});

Expand Down
26 changes: 21 additions & 5 deletions src/service/ngJwtAuthService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,15 @@ export class NgJwtAuthService {
;

//needs to refresh if the the next time we could refresh is after the configured refresh before date
return (latestRefresh <= nextRefreshOpportunity);
return (latestRefresh <= nextRefreshOpportunity || this.cookieIsMissing());
}

/**
* Check if there should be a cookie, but it is missing
* @returns {boolean}
*/
private cookieIsMissing():boolean {
return this.config.cookie.enabled && !this.$cookies.get(this.config.cookie.name);
}

/**
Expand Down Expand Up @@ -409,8 +417,11 @@ export class NgJwtAuthService {
this.$window.localStorage.removeItem(this.config.storageKeyName);

if (this.config.cookie.enabled) {

this.$cookies.remove(this.config.cookie.name);
let options = undefined;
if (this.config.cookie.topLevelDomainName) {
options = {domain: this.config.cookie.topLevelDomainName}
}
this.$cookies.remove(this.config.cookie.name, options);
}

this.unsetJWTHeader();
Expand Down Expand Up @@ -573,8 +584,12 @@ export class NgJwtAuthService {
let cookieKey = this.config.cookie.name,
expires = new Date(tokenData.data.exp * 1000); //set the cookie expiry to the same as the jwt

if (this.config.cookie.topLevelDomain) {

if (this.config.cookie.topLevelDomainName) {
this.$cookies.put(cookieKey, rawToken, {
domain: this.config.cookie.topLevelDomainName,
expires: expires,
});
} else if (this.config.cookie.topLevelDomain) {
let hostnameParts = this.$location.host().split('.');
let segmentCount = 1;
let testHostname = '';
Expand All @@ -588,6 +603,7 @@ export class NgJwtAuthService {
});

if (this.$cookies.get(cookieKey)) { //saving the cookie worked, it must be the top level domain
this.config.cookie.topLevelDomainName = testHostname;
return; //so exit here
}

Expand Down