Git Product home page Git Product logo

angular-oauth2-oidc's Issues

Support for Deep Linking

I'd like to support the following scenario:

  1. user bookmarks a view (or sends a link to collegue)
  2. the user session expires
  3. user clicks the link
  4. the user is prompted for login if necessary
  5. the desired view is displayed

At first, this sounds trivial, simply add the proper redirect URI:

oauthService.redirectUri = window.location.href;

until one meets an OpenID Connect provider that does not support wildcards in authorized redirect urls (yes Google, I am looking at you ...)

I guess I could specify a redirect URI like "redirect.html?target=the_deep_link" and hook into the router to intercept this URL, parse the query param, and redirect to the actual target once the token has been verified. This has the advantage that asynchronous token verification (due to asynchronous loading of the discovery document) would be invisible to the actual application route, i.e. a component constructor could issue backend requests without needing to wait for a login promise.

Do you see a better solution? If not, would you accept a PR implementing this?

how to use password pattern without discovery document?

when i use password pattern without discovery document, occur errors.
project can not do the right request to the auth-server.

constructor(private oauthService: OAuthService) {

    // Login-Url
    this.oauthService.loginUrl = 'https://accounts.google.com/o/oauth2/v2/auth'; //Id-Provider?

    // URL of the SPA to redirect the user to after login
    this.oauthService.redirectUri = window.location.origin;

    // The SPA's id. Register SPA with this id at the auth-server
    this.oauthService.clientId = '<client-id>';

    // set the scope for the permissions the client should request
    this.oauthService.scope = 'profile email https://www.googleapis.com/auth/drive';

    // set to true, to receive also an id_token via OpenId Connect (OIDC) in addition to the
    // OAuth2-based access_token
    this.oauthService.oidc = true;

    // Use setStorage to use sessionStorage or another implementation of the TS-type Storage
    // instead of localStorage
    this.oauthService.setStorage(sessionStorage);
    this.oauthService.issuer = 'https://www.googleapis.com';

    // To also enable single-sign-out set the url for your auth-server's logout-endpoint here
    // this.oauthService.logoutUrl = "https://steyer-identity-server.azurewebsites.net/identity/connect/endsession?id_token={{id_token}}";

    // Set a dummy secret
    // Please note that the auth-server used here demand the client to transmit a client secret, although
    // the standard explicitly cites that the password flow can also be used without it. Using a client secret
    // does not make sense for a SPA that runs in the browser. That's why the property is called dummyClientSecret
    // Using such a dummy secreat is as safe as using no secret.
    this.oauthService.dummyClientSecret = '<client-secret>';

    // This method just tries to parse the token(s) within the url when
    // the auth-server redirects the user back to the web-app
    // It dosn't send the user the the login page
    this.oauthService.tryLogin({
      onTokenReceived: (context) => {
        console.log('logged in', context);
      }
    });
    
  }

2017-07-19_100933

Problem with typings install

Angular doesn't use typings anymore. Now it has dependency on @types, eg.
"devDependencies": { "@types/node": "^6.0.45", "@types/jasmine": "^2.5.35" }

When imported to project with no typings it throws an error:
npm ERR! [email protected] postinstall: typings install
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] postinstall script 'typings install'.
npm ERR! Make sure you have the latest version of node.js and npm installed.

It's propably due to use of typings, and specifying it only in devDependancies.

login implicitflow method keeps looping redirecting hp, doesn't go to loginurl

I created an authservice with all parameters filled in

constructor(private oauthService: OAuthService) {

      // Login-Url
      this.oauthService.loginUrl = "https://login.microsoftonline.com/TENANT_ID_GUID/oauth2/authorize";

      // URL of the SPA to redirect the user to after login
      this.oauthService.redirectUri = window.location.origin + "/";

      // The SPA's id. Register SPA with this id at the auth-server
      this.oauthService.clientId = '';

      // set the scope for the permissions the client should request
      this.oauthService.scope = "openid profile";

      // set to true, to receive also an id_token via OpenId Connect (OIDC) in addition to the
      // OAuth2-based access_token
      this.oauthService.oidc = true;

      //resourceAppId from manifest; required because requesting id_token AND token.  Would not be requied for just id_token...
      this.oauthService.resource = '';

      // Use setStorage to use sessionStorage or another implementation of the TS-type Storage
      // instead of localStorage
      this.oauthService.setStorage(sessionStorage);

      // To also enable single-sign-out set the url for your auth-server's logout-endpoint here
      this.oauthService.logoutUrl = "https://login.microsoftonline.com/TENANT_ID_GUID/oauth2/logout?id_token={{id_token}}";

      this.oauthService.issuer = "https://sts.windows.net/TENANT_ID_GUID/";

      // This method just tries to parse the token(s) within the url when
      // the auth-server redirects the user back to the web-app
      // It dosn't send the user the the login page
      this.oauthService.tryLogin({
          onTokenReceived: context => {
              var claims = context.idClaims;
              var currentUser = {
                  name: claims.name,
                  id: claims.unique_name,
                  roles: claims.roles
              };
              sessionStorage.setItem('currentUser', JSON.stringify(currentUser));
           }
       });
    }

Then a authguard on homepage for homepage

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private oauthService: OAuthService, private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
    if (this.oauthService.hasValidIdToken()) {
      return true;
    }

    this.oauthService.initImplicitFlow();
    return false;
  }
}

the this.oauthService.initImplicitFlow(); just keeps looping and refreshing homepage, there is stuff in the url but that's it. It doesn't go to login url, any ideas? here is repo https://github.com/premiumwd/a

Does not work for GitHub

I tried multiple approaches for logging in with GitHub, but it does not log me in. I can approve the app and it returns the code and state in the url, but it does not do the second step and gets the token.

No need to import all of rxjs

This statement in oauth-service.ts imports ALL of rxjs which increases the size of app by a large amount. It's unnecessary.

import { Observable, Observer } from 'rxjs';

replacing it by this:

import { Observable } from 'rxjs/Observable';
import { Observer } from 'rxjs/Observer';

would dramatically reduce the size of the app.

Authorization Code Flow support

When are you planning to add support for the Authorization Code Flow?

Should be reasonably easy given that you already implemented all logic for identity, access, and refresh tokens, including refreshing the access token with the refresh token - or am I missing something?

canActivate Route

When I try to use canActivate on a route it always returns false. I am doing an implicit flow and when it redirects back it seems like it does not wait for the service to be aware of the login and it always redirects back to the login page.

`@Injectable()
export class AuthGuardService implements CanActivate {

constructor (
    private _oauthService: OAuthService,
    private _router: Router
) {

}

canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.loggedIn) {
        return true;
    }

    //Redirect the user before denying them access to this route
    this._router.navigate(['/welcome']);
    return false;
}

get loggedIn() {
    return this._oauthService.hasValidAccessToken();
}

}`

Not working with Slack

This is my configuration:

constructor(private oAuthService: OAuthService) {
    this.oAuthService.loginUrl = 'https://slack.com/oauth/authorize';
    this.oAuthService.redirectUri = '<redirect_uri>';
    this.oAuthService.clientId = '<client_id>';
    this.oAuthService.scope = 'commands users:read.email chat:write:bot channels:write channels:read users:read';
    this.oAuthService.tryLogin({
      onTokenReceived: context => {
        console.debug("logged in");
        console.debug(context);
      }
    });
}

Slack redirects to <redirect_uri> passing the parameters code and state.

http://<domain>/?code=<code>&state=<state>

Looking at the oauth page from slack (https://api.slack.com/docs/oauth), these are the following steps:

  1. Authorization (https://slack.com/oauth/authorize)
  2. Token Issuing (https://slack.com/api/oauth.access)

How can I make it work with Slack?

logOut() does not end session on ID provider

I have the following configured in my AppComponent:

export class AppComponent {

    constructor(private router: Router,
        private oauthService: OAuthService) {

        // Login-Url
        this.oauthService.loginUrl = "https://login.microsoftonline.com/TENANT_ID_GUID/oauth2/authorize";

        // URL of the SPA to redirect the user to after login
        this.oauthService.redirectUri = window.location.origin + "/";

        // The SPA's id. Register SPA with this id at the auth-server
        this.oauthService.clientId = CLIENT_ID_GUID;

        // set the scope for the permissions the client should request
        this.oauthService.scope = "openid profile";

        // set to true, to receive also an id_token via OpenId Connect (OIDC) in addition to the
        // OAuth2-based access_token
        this.oauthService.oidc = true;

        //resourceAppId from manifest; required because requesting id_token AND token.  Would not be requied for just id_token...
        this.oauthService.resource = RESOURCE_ID_GUID;

        // Use setStorage to use sessionStorage or another implementation of the TS-type Storage
        // instead of localStorage
        this.oauthService.setStorage(sessionStorage);

        // To also enable single-sign-out set the url for your auth-server's logout-endpoint here
        this.oauthService.logoutUrl = "https://login.microsoftonline.com/TENANT_ID_GUID/oauth2/logout?id_token={{id_token}}";

        this.oauthService.issuer = "https://sts.windows.net/TENANT_ID_GUID/";

        // This method just tries to parse the token(s) within the url when
        // the auth-server redirects the user back to the web-app
        // It dosn't send the user the the login page
        this.oauthService.tryLogin({
            onTokenReceived: context => {
                var claims = context.idClaims;
                var currentUser = {
                    name: claims.name,
                    id: claims.unique_name,
                    roles: claims.roles
                };
                sessionStorage.setItem('currentUser', JSON.stringify(currentUser));
            }
        });
}

When I call oauthService.logOut(), it does not end the session on the ID provider server (Azure AD). If I call oauthService.getAccessToken() it returns null and oauthService.hasValidAccessToken() returns false, but if I navigate to my ID provider login page (https://login.microsoftonline.com), my session is still active.

FWIW, I'm using v1.0.20.

localStorage not defined

Hello everyone,

I´m trying to build an Angular2 project with IdentityServer4 following this post: [https://www.softwarearchitekt.at/post/2016/07/03/authentication-in-angular-2-with-oauth2-oidc-and-guards-for-the-newest-new-router-english-version.aspx].

The fact is that I can´t run the application because i receive the following error once I load it:
localStorage is not defined at new OAuthService

Thanks and regards

Userinfo Endpoint undefined

I'm trying to setup the OAuthService to use a user info endpoint and I have defined this as follows:
this.oauthService.userinfoEndpoint = "https://login.microsoftonline.com/common/openid/userinfo";
However, when I look at the directory of the service, it says that userinfoEndpoint: undefined. Because of this, I'm not able to get the user details.

Extra state causes token parse to fail

Hi,

There is a bug in the tryLogin function. When you have additional state, the state is sent to the IDP as a string, seperated with ;. This is URL encoded due to it being passed around by the IDP, and then when the code tries to split the string later on, it cannot split the string on the delimiter ; and so the nonce checking fails.

https://github.com/manfredsteyer/angular-oauth2-oidc/blob/master/src/oauth-service.ts#L282-L294

A fix would be to URL decode the string before splitting the state by ;.

Cheers

Facebook/Google login

Hello,

Thank you for this excellent tool. I was wondering if you can provide an example using Facebook or Google login.
I tried but I faced CORS issues.

Thanks for your help !

Support for Angular Universal (localStorage dependency)

First off, I wanted to thank you for making this project--I've found it super useful, and it's very generous of you to contribute it!

I've been trying to adapt it to an app that uses Angular Universal using this starter template. The rub with Angular Universal in general is that global objects such as window or localStorage are not available when the page gets rendered on the server in the context of node (see list of gotchas here).

The approach I was trying out was to create a "mock" storage service to be injected into the OAuthService when it runs on the server. I could then write this service to take auth tokens from the http header of the client request, and pass them along to the OAuthService through my mock's implementation of the getItem method.

The issue I'm hitting is with this line - which causes the OAuthService class to (try to) be created with window.LocalStorage even before I've had a chance to override it with my mock storage service through the setStorage method. This causes the app to fail to render completely on the server side.

I've found that by modifying that line to instead simply not create a default value (e.g. private _storage: Storage; instead of private _storage: Storage = localStorage;, I can get things working. Obviously, making that change could break other people who had relied on the default behavior in a non-universal context.

One suggestion that might work for everyone would be to initialize the _storage variable in the constructor, but only if localStorage actually exists (which is true on the Browser, but not on the Server. This should keep things the same for anyone rendering in the browser, but also enable the server-render scenario as long as you call the setStorage method to your mock Storage object soon after initializing OAuthService. Something like this:

private _storage: Storage;
constructor(private http: Http) {
    if (typeof localStorage != undefined) {
        this._storage = localStorage;
    }
//Rest of the constructor
}

Do you like the idea of trying to support Angular Universal? If yes, what do you think of this general approach? I'm happy to submit a pull request, but I wanted to check with you first.

Documentation describing password flow is wrong

It seems that the documentation describing the password flow without discovery document is incorrect. The code snippet ends with a line that loads the discovery document (copy/paste issue?).

The snippet should IMO end with something like:

    this.oauthService.tokenEndpoint = 'https://steyer-identity-server.azurewebsites.net/identity/connect/token';
    this.oauthService.fetchTokenUsingPasswordFlow('max', 'geheim').then(() => {
      // ...
    });

?p=policy not supported (ad b2c)

Hi @manfredsteyer, first of all: great for sharing this, works great with ng 4! however i have a small issue with AD B2C and it's policies.

if i have a discovery url like :

https://login.microsoftonline.com/doomsdayb2c.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_signin

that will resolve in a login url :

https://login.microsoftonline.com/doomsdayb2c.onmicrosoft.com/oauth2/v2.0/authorize?p=b2c_1_signin

then the login will not work because the appended querystring (in createLoginUrl) starts with a ? too, that's one too much. do you accept a PR as a fix?

Routing Blocked with Additional Api Call - CanActivate Guard

Background/Scenario

In utilizing the library by hitting url 'someurl/1' as the initial page, my app sets the settings for the oauthservice on the app component constructor level. The AuthorizationGuardService then determines you are not authorized by using the oauthservice.hasValidIdToken() the default route configured to the login component kicks in and calls oauthservice.initImplicitFlow() triggering the IDP redirects which ultimately is returned to the same login route it came from. We check that oauthservice.hasValidIdToken() is true then redirect back to the guarded route. which also makes the same oauthService.hasValidIdToken() call and then an additional api call for permissions. This returns an observable boolean. When the observable/api call resolves, the guard should allow the route to pass through. It doesn't it just sits there without any error and never allows the protected route to load. The router seems to be cancelling navigation when tracing is on.

I removed the calls to the oauthService and the same method works fine ultimately resolving the protected route. The general code structure is below. Package version is 1.0.20 on angular 4.1.3.

app.component.ts

import { Component, Inject } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { AppConfig } from './app.config';

@Component({
    selector: 'my-app',
    styleUrls: [ './app.component.scss' ],
    templateUrl: './app.component.html'
})
export class AppComponent {
    constructor(private _config: AppConfig,
                private _oauthService: OAuthService) {
        this._oauthService.loginUrl = _config.settings.loginEndpoint;
        this._oauthService.redirectUri = _config.settings.redirectUri;
        this._oauthService.clientId = _config.settings.clientId;
        this._oauthService.scope = _config.settings.scope;
        this._oauthService.oidc = _config.settings.oidc;
        this._oauthService.tryLogin({});
    }
}

login.component.ts

import { Component, OnInit, Inject } from '@angular/core';
import { Router } from '@angular/router';
import { OAuthService } from 'angular-oauth2-oidc';

@Component({
  template: ''
})
export class LoginComponent implements OnInit {
  constructor(private _oauthService: OAuthService, private _router: Router) {
  }

  ngOnInit(): void {
    let id =1;

    if (this._oauthService.hasValidIdToken()) {
      if (id)
        this._router.navigate(['/someurl', id]);
    }
    else
      this.login();
  }

  login() {
    this._oauthService.initImplicitFlow();
  }
}

authorization.guard.service.ts

import { permissionServiceInterface, IPermissionService } from './../permission/permission.service';
import { OAuthService } from 'angular-oauth2-oidc';
import { Observable } from 'rxjs/Observable';
import { CanActivate, ActivatedRouteSnapshot, Router, RouterStateSnapshot, NavigationExtras } from '@angular/router';
import { Inject, Injectable } from '@angular/core';

@Injectable()
export class AuthorizationGuardService implements CanActivate {
    constructor(private _oauthService: OAuthService,
        private _router: Router,
        @Inject(permissionServiceInterface) private _permissionService: IPermissionService) {}

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Observable<boolean> | Promise<boolean> {
        let id = route.params['id'];

        if (this._oauthService.hasValidIdToken())
            return this.checkRoutePermissions(+id);

        this._router.navigate(['/login']);
        return false;
    }

    private checkRoutePermissions(id: number): Observable<boolean> {
        return this._permissionService.checkAuthority(id);
    }
}

permission.service.ts

import { Observable } from 'rxjs/Observable';
import { Router } from '@angular/router';
import { Http, Response } from '@angular/http';
import { Injectable, OpaqueToken } from '@angular/core';

export let permissionServiceInterface = new OpaqueToken('IPermissionService');

export interface IPermissionService {
    checkAuthority(id: number): Observable<boolean>;
}

@Injectable()
export class PermisisonService implements IPermissionService {
    private _apiUrl: string;

    constructor(private _http: Http, private _config: AppConfig,
                router: Router) {
        super(router);
        this._apiUrl = 'someurl';
    }

    checkAuthority(id: number): Observable<boolean> {
        this._apiUrl = 'someurl/id';

        return this._http.get(this._apiUrl)
                    .map((response) => {
                        return response.json() as boolean;
                    });
    }
}

Detection of wrong credentials for PasswordFlow

When the users passes credentials, that are not accepted by the identity provider, I would like to detect this and present an error message, pointing the user into the right direction. I cannot seem to get this to work, here is a code snippet:

 this.oauthService
            .fetchTokenUsingPasswordFlowAndLoadUserProfile(this.user.username, this.user.password)
            .then(() => {
                console.debug('successfully logged in');
                let claims = this.oauthService.getIdentityClaims();
                this.loginFailed = false;
            })
            .catch((err) => {
                console.error('error logging in', err);
                this.loginFailed = true;
                this.errorMessage = this.labels.APP_UNAVAILABLE;
            })

The err object is a ProgressEvent and I cannot find anything useful to differentiate the error that happened.
error

Is this currently supported?

getting unauthorized_client 400 error when logging in

Hi I need help,

anyone getting 400 error with unauthorized client error on submit request, anyone had issue?

click handler

public login() {

        console.log('email: ' + this.model.email, 'password: ' + this.model.password);
        
        if(this.model.email && this.model.password != null) {
            this.loading = true;
            this.oauthService.fetchTokenUsingPasswordFlow(this.model.email, this.model.password).then(
                result => {
                    this.token = this.oauthService.getAccessToken();
                },
                error => {
                    alert(error);
                    console.log(error);
                    this.token = error;
                    this.loading = false;
            })
        }
    }

fired on login submit

    public configureLogin(){  
        // URL of the SPA to redirect the user to after login
        this.oauthService.redirectUri = window.location.origin;

        // The SPA's id. The SPA is registerd with this id at the auth-server
        this.oauthService.clientId = "testClient";

        // set the scope for the permissions the client should request
        // The first three are defined by OIDC. The 4th is a usecase-specific one
        this.oauthService.scope = "openid profile email TestScope";

        // set to true, to receive also an id_token via OpenId Connect (OIDC) in addition to the
        // OAuth2-based access_token
        this.oauthService.oidc = true;

        this.oauthService.dummyClientSecret = "secret";

        // Use setStorage to use sessionStorage or another implementation of the TS-type Storage
        // instead of localStorage
        this.oauthService.setStorage(sessionStorage);

        // The name of the auth-server that has to be mentioned within the token
        this.oauthService.issuer = "https://phenomenexauthserver.azurewebsites.net/";
        
        // Load Discovery Document and then try to login the user
        this.oauthService.loadDiscoveryDocument().then(() => {

            // This method just tries to parse the token(s) within the url when
            // the auth-server redirects the user back to the web-app
            // It dosn't send the user the the login page
            this.oauthService.tryLogin({});      

        });
    }

Add postLogoutRedirectUri as a separate property to OAuthService

It would be nice to have a separate property on OAuthService for the postLogoutRedirectUri, so that the service can be configured all at once, rather than having to set the redirectUri before calling logout.

...
        public redirectUri = "";
        public postLogoutRedirectUri = "";
...

For backward compatibility, the service should fall back on the redirectUri:

...
        let logoutUrl: string;
        
        // For backward compatibility
        if (this.logoutUrl.indexOf('{{') > -1) {
            logoutUrl = this.logoutUrl.replace(/\{\{id_token\}\}/, id_token);
        }
        else {
            logoutUrl = this.logoutUrl + "?id_token_hint=" 
                                + encodeURIComponent(id_token)
                                + "&post_logout_redirect_uri="
                                + encodeURIComponent(this.postLogoutRedirectUri || this.redirectUri);
        }
        location.href = logoutUrl;
...

Is it possible to subscribe to authentication so navigation isn't needed on logout?

First of all, thanks for this great library! I've been using it to show how to interact with Okta's OIDC and OAuth support.

I'm trying to use it in an Ionic app and I've run into an issue navigating on logout. I posted this question to the Ionic forums to see about how to workaround a logout issue. As you can see, I received a reply that I should simply subscribe to an event to do my navigation. For example:

authService.notifier.subscribe((authed) => {
  if (authed) {
    this.rootPage = TabsPage;
  } else {
    this.rootPage = LoginPage;
  }
});

Does this library provide that feature?

Is it possible to save the token?

Is it possible to save the token for use later and then verify if the token is valid before requesting a new one?

Edit: Use case would be allowing a user to book mark a certain "page" within the app and then navigate back to it using the saved token instead of requesting a new one and then being redirected back to the landing page.

I know you can change the storage to "localStorage" but the module doesn't seem to utilize the stored key.

Return URLs with ? not properly parsed

When the return URL looks like

https://localhost:6001/#/home?id_token=...&access_token=...&token_type=Bearer
&expires_in=3600&scope=...&state=...&session_state=...

then I get the following JSON from getFragment()

{
  "home?id_token": "...",
  "access_token": "...",
  "token_type": "Bearer",
  "expires_in": "3600",
  "scope": "...",
  "state": "...",
  "session_state": "..."
}

obviously, the home? part should not be in this json. Apparently the issue is because the method getFragment, which parses everything after the # sign, instead of everything after the ? sign:

    getFragment() {
        if (window.location.hash.indexOf("#") === 0) {
            return this.parseQueryString(window.location.hash.substr(1));
        } else {
            return {};
        }
    };

it should probably look like:

    getFragment() {
         const questionMarkPosition = window.location.href.indexOf('?');
         if (questionMarkPosition >= 0) {
             var queryString = window.location.href.slice(questionMarkPosition + 1);
             return this.parseQueryString(queryString);
        }

        if (window.location.hash.indexOf("#") === 0) {
            return this.parseQueryString(window.location.hash.substr(1));
        }

        return {};
        }
    };

OAuthService.logOut(true) doesn't log the user out from the identity server

In short: OAuthService.logOut(true) clears the identity token from the client application but does not log the user out of the identity server itself.

Angular2 application signs in to Identity Server via OIDC and is redirected back to the angular2 app. The angular2 app has a "logout" button which corresponds to OAuthService.logOut(). The parameter to logOut() is "noRedirectToLogoutUrl?: boolean" which, if true, clears the identity token from the angular2 application but not from the identity server, i.e. if the user tries to log in from the angular2 app, they are automatically signed in by the identity server and redirected back to the angular2 app. To me this is unexpected behavior: I want the user signed out of both the angular2 app AND the identity server.

If instead I call OAuthService.logOut(false) then the behavior is as expected except now the user needs to manually navigate back to the angular2 app (which I want to avoid).

Response Type

Hi, I'm implementing an OAuth 2.0 client for the first time, so I may be doing something incorrectly, but I believe I need to be able to customize the responseType parameter. The server I'm working with expects a response_type of code for requesting an authorization code. Here is a section of the OAuth 2.0 spec:

response_type
REQUIRED. The value MUST be one of "code" for requesting an authorization code as described by Section 4.1.1, "token" for requesting an access token (implicit grant) as described by Section 4.2.1, or a registered extension value as described by Section 8.4.
-- https://tools.ietf.org/html/rfc6749#page-19

Currently, the responseType can't be set manually, and can only be set to token or id_token+token (if OIDC is being used).

Can't authenticate with tokens signed using xx384 or xx512 algorithms when at_hash is included

According to http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken, the at_hash claim contains "the base64url encoding of the left-most half of the hash of the octets of the ASCII representation of the access_token value, where the hash algorithm used is the hash algorithm used in the alg Header Parameter of the ID Token's JOSE Header". The current implementation only uses SHA-256 and fails to process tokens signed with algorithms such as RS384 and ES512 since they use correspondingly larger hash algorithms for at_hash.

"expires_in" does not work

Hi,

the key for "expires_in" in line 286 of oauth-service.ts seems to be incorrect. Regarding openId Spec

Instead of
this.storeAccessTokenResponse(accessToken, null, parts['expiresIn']);
it should be
this.storeAccessTokenResponse(accessToken, null, parts['expires_in']);
if i'm correct.

The old version of this library had it correct.

Thanks in advance

Uncaught SyntaxError: Unexpected token import

Hello,

  1. I added "angular-oauth2-oidc" dependency

  2. angular-cli.json
    "scripts": [
    "../node_modules/angular-oauth2-oidc/index.ts"
    ],

  3. getting this following error
    Uncaught SyntaxError: Unexpected token import
    at eval ()
    at webpackJsonp.../../../../script-loader/addScript.js.module.exports (addScript.js:9)
    at Object.../../../../script-loader/index.js!../../../../angular-oauth2-oidc/index.ts (index.ts?3cee:1)
    at webpack_require (bootstrap 59ce402…:54)
    at Object.2 (scripts.bundle.js:37)
    at webpack_require (bootstrap 59ce402…:54)
    at webpackJsonpCallback (bootstrap 59ce402…:25)
    at scripts.bundle.js:1

OAuthModule.forRoot() giving me an error.

ERROR in Error encountered resolving symbol values statically. Calling function 'OAuthModule', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function, resolving symbol AppModule in directory/oAuth/src/app/app.module.ts, resolving symbol AppModule in directory/oAuth/src/app/app.module.ts

Question about scenario

so if I opt for manual clicks for logon/logoff, I can get this working no problem with my implicit provider. I'd like to basically say spa as a whole is blocked without authentication.

I've basically put something in place that loads the discovery doc, then tries to login. After that oauthservice .hasIdToken(), I initiate the implicitflow().

No combination of router guards and those checks will end up breaking before we present any user interface, and was wondering how people are achieving this effect. There is no user interface for unauthenticated users. I could just enforce the index.html doesnt get served it not authenticated... but seems like I should be able to achieve this here as well.

My router guard experiments resulted in weird looping between my oidc server and the opening component.

handle error when idp returns error login in

if the user does not successfully login in the idp then an error is returned eg:

image

EXCEPTION: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'error'
Error: Cannot match any routes. URL Segment: 'error'
    at ApplyRedirects.noMatchError (http://localhost:4200/vendor.bundle.js:108860:16) [angular]
    at CatchSubscriber.selector (http://localhost:4200/vendor.bundle.js:108829:29) [angular]
    at CatchSubscriber.error (http://localhost:4200/vendor.bundle.js:50636:31) [angular]
    at MapSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at MapSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at MapSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at MapSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at MapSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at MapSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at LastSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at LastSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at MergeAllSubscriber.OuterSubscriber.notifyError (http://localhost:4200/vendor.bundle.js:632:26) [angular]
    at InnerSubscriber._error (http://localhost:4200/vendor.bundle.js:115288:21) [angular]
    at InnerSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
window.console.error @ VM13634:27
VM13634:27 ORIGINAL STACKTRACE:
window.console.error @ VM13634:27
VM13634:27 Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'error'
Error: Cannot match any routes. URL Segment: 'error'
    at ApplyRedirects.noMatchError (apply_redirects.js:149) [angular]
    at CatchSubscriber.selector (apply_redirects.js:118) [angular]
    at CatchSubscriber.error (catch.js:104) [angular]
    at MapSubscriber.Subscriber._error (Subscriber.js:128) [angular]
    at MapSubscriber.Subscriber.error (Subscriber.js:102) [angular]
    at MapSubscriber.Subscriber._error (Subscriber.js:128) [angular]
    at MapSubscriber.Subscriber.error (Subscriber.js:102) [angular]
    at MapSubscriber.Subscriber._error (Subscriber.js:128) [angular]
    at MapSubscriber.Subscriber.error (Subscriber.js:102) [angular]
    at LastSubscriber.Subscriber._error (Subscriber.js:128) [angular]
    at LastSubscriber.Subscriber.error (Subscriber.js:102) [angular]
    at MergeAllSubscriber.OuterSubscriber.notifyError (OuterSubscriber.js:22) [angular]
    at InnerSubscriber._error (InnerSubscriber.js:26) [angular]
    at InnerSubscriber.Subscriber.error (Subscriber.js:102) [angular]
    at resolvePromise (zone.js:643) [angular]
    at resolvePromise (zone.js:619) [angular]
    at :4200/vendor.bundle.js:131681:17 [angular]
    at Object.onInvokeTask (ng_zone.js:264) [angular]
    at ZoneDelegate.invokeTask (zone.js:362) [angular]
    at Zone.runTask (zone.js:166) [<root> => angular]
    at drainMicroTaskQueue (zone.js:529) [<root>]
window.console.error @ VM13634:27
VM13634:27 Unhandled Promise rejection: Cannot match any routes. URL Segment: 'error' ; Zone: angular ; Task: Promise.then ; Value: ZoneAwareError Error: Cannot match any routes. URL Segment: 'error'
    at ApplyRedirects.noMatchError (http://localhost:4200/vendor.bundle.js:108860:16) [angular]
    at CatchSubscriber.selector (http://localhost:4200/vendor.bundle.js:108829:29) [angular]
    at CatchSubscriber.error (http://localhost:4200/vendor.bundle.js:50636:31) [angular]
    at MapSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at MapSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at MapSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at MapSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at MapSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at MapSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at LastSubscriber.Subscriber._error (http://localhost:4200/vendor.bundle.js:483:26) [angular]
    at LastSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
    at MergeAllSubscriber.OuterSubscriber.notifyError (http://localhost:4200/vendor.bundle.js:632:26) [angular]
    at InnerSubscriber._error (http://localhost:4200/vendor.bundle.js:115288:21) [angular]
    at InnerSubscriber.Subscriber.error (http://localhost:4200/vendor.bundle.js:457:18) [angular]
window.console.error @ VM13634:27
VM13634:27 ZoneAwareError

Not working without Document Discovery

Maybe I'm misunderstanding how this is supposed to be working. But I'm attempting to use it for OAuth with a provider that doesn't have a publicly accessible discovery document for their OpenID Configuration. I've tried for hours to get this working but it never actually navigates to the providers login/consent page. If I take the login url that is generated out of the library and paste that in my browser it takes me to their consent screen just as expected. In order to test the theory, I have been able to get a working example using Google as a provider with Document Discovery. If I take the exact values that are extracted from their openid-configuration and set them manually and remove Document Discovery, it stops working and in fact behaves just like the other provider. Below are the configurations I'm using for Google with and without Document Discovery.

With Discovery:

constructor(private oauthService: OAuthService) {
    this.oauthService.redirectUri = window.location.origin + '/index.html';
    this.oauthService.clientId = '<client-id>';
    this.oauthService.scope = 'openid email profile';
    this.oauthService.oidc = true;
    this.oauthService.setStorage(sessionStorage);
    this.oauthService.issuer = 'https://accounts.google.com'
    this.oauthService.loadDiscoveryDocument().then(() => {
      this.oauthService.tryLogin({
        onTokenReceived: context => {
          console.log('logged in');
          console.log(context);
        }
      });
    });
  }

  public login(): void {
    this.oauthService.initImplicitFlow();
  }

Without Discovery:

this.oauthService.loginUrl = 'https://accounts.google.com/o/oauth2/v2/auth';
    this.oauthService.tokenEndpoint = 'https://www.googleapis.com/oauth2/v4/token';
    this.oauthService.userinfoEndpoint = 'https://www.googleapis.com/oauth2/v3/userinfo';
    this.oauthService.redirectUri = window.location.origin + '/index.html';
    this.oauthService.clientId = '<client-id>';
    this.oauthService.scope = 'openid email profile';
    this.oauthService.oidc = true;
    this.oauthService.setStorage(sessionStorage);
    this.oauthService.issuer = 'https://accounts.google.com';
    this.oauthService.tryLogin({});

Error

I have this error

Failed to load resource: the server responded with a status of 404 (Not Found)
localhost/:51 (SystemJS) XHR error (404 Not Found) loading http://localhost:5555/node_modules/angular-oauth2-oidc.js
Error: XHR error (404 Not Found) loading http://localhost:5555/node_modules/angular-oauth2-oidc.js
at XMLHttpRequest.wrapFn [as _onreadystatechange] (http://localhost:5555/node_modules/zone.js/dist/zone.js?1486029206310:1039:29) []
at Zone.runTask (http://localhost:5555/node_modules/zone.js/dist/zone.js?1486029206310:151:47) [ => ]
at XMLHttpRequest.ZoneTask.invoke (http://localhost:5555/node_modules/zone.js/dist/zone.js?1486029206310:345:33) []
Error loading http://localhost:5555/node_modules/angular-oauth2-oidc.js as "angular-oauth2-oidc" from http://localhost:5555/app/app.module.js Not expecting this error? Report it at https://github.com/mgechev/angular-seed/issues
(anonymous) @ (index):51
http://localhost:5555/node_modules/angular-oauth2-oidc.js Failed to load resource: the server responded with a status of 404 (Not Found)

Error after upgrading angular-cli

I get the following error after upgrading angular-cli:

ERROR in Error encountered resolving symbol values statically. Calling function 'OAuthModule', function calls are not supported. Consider replacing the function or lambda with a refer
ence to an exported function, resolving symbol AppModule in ...

It looks like there is an error in the angular part, but for the moment i can't use your package and i'm not sure if the angular team will change anything. I've compared your package with working code from FexLayoutModule or MaterialModule, but i don't get the difference... :-(

Here is the issue depending to this:
angular/angular#13931

Perhaps you know a solution for that, or gues whether the problem is in your, mine or the angular part :-)

Remove core-js reference from oauth-service.d.ts

In short: the reference is not needed and causes conflicts with lib-es6.d.ts

Scenario:

  • Follow the Angular2 Webpack sample to create an Angular2 app that builds with Webpack
  • Add the angular-oauth2-oidc package and use it to protect the AppComponent
  • Attempting to build the application fails because oauth-service.d.ts references core-js, which wasn't installed -- so install core-js via npm install @types/core-js --save-dev
  • Attempting to build the application fails because core-js conflicts with lib-es6.d.ts (duplicate identifier 'PropertyKey')
  • Uninstall core-js via npm uninstall @types/core-js --save-dev
  • Open oauth-service.d.ts and delete the line /// <reference types="core-js" />
  • Building the application now succeeds

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.