Coder Social home page Coder Social logo

damienbod / angular-auth-oidc-client Goto Github PK

View Code? Open in Web Editor NEW
1.1K 37.0 422.0 17.17 MB

npm package for OpenID Connect, OAuth Code Flow with PKCE, Refresh tokens, Implicit Flow

Home Page: https://www.npmjs.com/package/angular-auth-oidc-client

License: MIT License

JavaScript 10.28% TypeScript 86.81% HTML 2.63% CSS 0.28%
openid angular implicit-flow npm security oauth2 oidc authn auth identity

angular-auth-oidc-client's Introduction

Angular Lib for OpenID Connect & OAuth2

Build Status npm npm npm code style: prettier Coverage Status

Secure your Angular app using the latest standards for OpenID Connect & OAuth2. Provides support for token refresh, all modern OIDC Identity Providers and more.

Acknowledgements

This library is certified by OpenID Foundation. (RP Implicit and Config RP)

Features

Installation

Ng Add

You can use the schematics and ng add the library.

ng add angular-auth-oidc-client

And answer the questions. A module will be created which encapsulates your configuration.

angular-auth-oidc-client schematics

Npm / Yarn

Navigate to the level of your package.json and type

 npm install angular-auth-oidc-client

or with yarn

 yarn add angular-auth-oidc-client

Documentation

Read the docs here

Samples

Explore the Samples here

Quickstart

For the example of the Code Flow. For further examples please check the Samples Section.

If you have done the installation with the schematics, these modules and files should be available already!

Configuration

Import the AuthModule in your module.

import { NgModule } from '@angular/core';
import { AuthModule, LogLevel } from 'angular-auth-oidc-client';
// ...

@NgModule({
  // ...
  imports: [
    // ...
    AuthModule.forRoot({
      config: {
        authority: '<your authority address here>',
        redirectUrl: window.location.origin,
        postLogoutRedirectUri: window.location.origin,
        clientId: '<your clientId>',
        scope: 'openid profile email offline_access',
        responseType: 'code',
        silentRenew: true,
        useRefreshToken: true,
        logLevel: LogLevel.Debug,
      },
    }),
  ],
  // ...
})
export class AppModule {}

And call the method checkAuth() from your app.component.ts. The method checkAuth() is needed to process the redirect from your Security Token Service and set the correct states. This method must be used to ensure the correct functioning of the library.

import { Component, OnInit, inject } from '@angular/core';
import { OidcSecurityService } from 'angular-auth-oidc-client';

@Component({
  /*...*/
})
export class AppComponent implements OnInit {
  private readonly oidcSecurityService = inject(OidcSecurityService);

  ngOnInit() {
    this.oidcSecurityService
      .checkAuth()
      .subscribe((loginResponse: LoginResponse) => {
        const { isAuthenticated, userData, accessToken, idToken, configId } =
          loginResponse;

        /*...*/
      });
  }

  login() {
    this.oidcSecurityService.authorize();
  }

  logout() {
    this.oidcSecurityService
      .logoff()
      .subscribe((result) => console.log(result));
  }
}

Using the access token

You can get the access token by calling the method getAccessToken() on the OidcSecurityService

const token = this.oidcSecurityService.getAccessToken().subscribe(...);

And then you can use it in the HttpHeaders

import { HttpHeaders } from '@angular/common/http';

const token = this.oidcSecurityServices.getAccessToken().subscribe((token) => {
  const httpOptions = {
    headers: new HttpHeaders({
      Authorization: 'Bearer ' + token,
    }),
  };
});

You can use the built in interceptor to add the accesstokens to your request

AuthModule.forRoot({
  config: {
    // ...
    secureRoutes: ['https://my-secure-url.com/', 'https://my-second-secure-url.com/'],
  },
}),
 providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
  ],

Versions

Current Version is Version 18.x

License

MIT

Authors

angular-auth-oidc-client's People

Contributors

adiessl avatar damienbod avatar dependabot[bot] avatar dome4 avatar erichjsonfosse avatar fabiangosebrink avatar gabrielgil avatar hwouters avatar izahirclemencia avatar jcannata avatar jerrettdavis avatar juanpgarces avatar linjie997 avatar movgp0 avatar normandjulian avatar openpef avatar pavankjadda avatar profet23 avatar projectaki avatar r4hulp avatar remkoboschker avatar robisim74 avatar samuel-b-d avatar schoes avatar taraskovalenko avatar timdeschryver avatar tom-v avatar valdian avatar vit100 avatar yberion avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-auth-oidc-client's Issues

CORS not enabled on Microsoft well known endpoints

My understanding might be totally wrong. But I wanted to have a discussion around the same.

I was testing the library from ng app hosted on localhost:4200. I am authenticating against Azure AD app (implicit flow). The auth flow gets stuck while getting signing keys.

It appears the some key discovery endpoints (e.g. jwks_uri: https://login.microsoftonline.com/common/discovery/keys, userinfo : https://login.microsoftonline.com/common/openid/userinfo ) do not have CORS enabled. We can not make an XHR request to retrieve information post callback.

Have you guys encountered this error before? am I missing something here?

This is the flow -

  1. Login method initiates auth url generation
  2. Round trip to auth url and retrieval of access token, state etc.
  3. Get signing keys (throws CORS error).
  4. Post validation, get user information (thrown CORS error after I explicitly tried to skip token validation)

Opened an issue since couldn't find better channel to talk.

error screenshot

Cheers,
Rahul.

jsrsasign dependency

I think the library should handle dependency on jsrsasign, so the developer doesn't have to do it 'manually'. Should figure out a proper way to do it.

Support isAuthorized$: Observable<boolean>

In my component I have a property bound to the isAuthorized which remains false since authorizedCallback is async.

ngOnInit() {
    if (window.location.hash) {
      this.oidcSecurityService.authorizedCallback();
    }
    this.authenticated = this.oidcSecurityService.isAuthorized;
  }

The way I got around this is by subscribing to the onUserDataLoaded EventEmitter, but it feels like there should be an Observable that can emit specifically for this property.

storage provider undefined

If no provider is defined, the module causes the app to crash. Temp fix remove provider from constructor in version 1.0.6,, and replaced with a setStorage method.

TODO test with side app
documentation

@astegmaier had to reset this, recieved angular errors when no provider was defined per default.

authorizedCallback called before wellknown endpoint is discovered

The authorize callback function tries to access the jwk_uris from the well known discovery endpoint without checking and waiting for the endpoint to load.

In certain edge cases, where the configuring module is loaded later, and the discovery of the well known configuration arrives after the call of the authorizeCallback, the authorizeCallback fails with the following error message:

jwks_uri: undefined
angular-auth-oidc-client.es5.js:1495 Unexpected token < in JSON at position 0
OidcSecurityService.handleErrorGetSigningKeys @ angular-auth-oidc-client.es5.js:1495
CatchSubscriber.error @ catch.js:104
MapSubscriber._next @ map.js:80
Subscriber.next @ Subscriber.js:89
onLoad @ http.es5.js:1226
ZoneDelegate.invokeTask @ zone.js:424
onInvokeTask @ core.es5.js:3924
ZoneDelegate.invokeTask @ zone.js:423
Zone.runTask @ zone.js:191
ZoneTask.invoke @ zone.js:486
core.es5.js:1020 ERROR Unexpected token < in JSON at position 0

To fix such timing issues it would be best to wait for the well known config Observable to complete and then parse the callback token.

this.authWellKnownEndpoints.onWellKnownEndpointsLoaded
            .concat(this.http.get(this.authWellKnownEndpoints.jwks_uri)
            .map(this.extractData)
            .catch(this.handleErrorGetSigningKeys));

Error: No provider for Router!

I get this when I try to run my app.
I guess you left this so the developer perforns the configuration by himself, right?
What happens if I'm using another routing provider like ui-router??

Firefox & Well known endpoints must be loaded before user can login

I might be missing something obvious here or I've discovered a bug.

I'm getting an error "Well known endpoints must be loaded before user can login!" when I call securityService.authorize() but only in Firefox. In Chrome and IE11 this works properly and redirects to the login page.

I am using the implicit flow. I'm using angular-auth-oidc-client 1.3.0, Firefox 54.0.1, Angular 4.3.1. This same problem also happens in a different angular 4+ app using angular-auth-oidc-client 1.3.0. It also happens to all 3 coworkers that I tested firefox with in both apps.

image

This is the setup code:
`initOpenIdServer(): OpenIDImplicitFlowConfiguration {

    if (this.openIdConfiguration != null)
        return this.openIdConfiguration;

    let implicitFlow = new OpenIDImplicitFlowConfiguration();

    implicitFlow.stsServer = this.cs.config.openIdBaseApiUrl;
    implicitFlow.redirect_url = this.cs.config.openIdRedirectUrl;
    implicitFlow.post_logout_redirect_uri = this.cs.config.openIdRedirectUrl;

    implicitFlow.client_id = 'my.id';
    implicitFlow.response_type = 'id_token token';
    implicitFlow.scope = 'openid profile email';

    implicitFlow.start_checksession = true;
    implicitFlow.silent_renew = true;
    implicitFlow.max_id_token_iat_offset_allowed_in_seconds = 10;

    implicitFlow.log_console_warning_active = true;
    implicitFlow.log_console_debug_active = false;

    implicitFlow.startup_route = '/';
    implicitFlow.forbidden_route = '/forbidden';
    implicitFlow.unauthorized_route = '/unauthorized';

    this.securityService.setupModule(implicitFlow);

    return implicitFlow;
}

`

I have verified the values coming from config files are correct before this code runs.

Is there something I should be doing with implicitFlow.override_well_known_configuration or implicitFlow.override_well_known_configuration_url? Do I need to provide different storage for FireFox?

External config JSON -- Authorize() - Cannot read property 'storage' of undefined

Hi,

I'd like to be able to pull the openIDImplicitFlowConfiguration configuration from an external JSON file and assign its values to the openIDImplicitFlowConfiguration object before passing it to the setupModule() method.

I've "outsourced" openIDImplicitFlowConfiguration's properties setting to an Angular service, in order to keep the AppModule clean. The service gets the JSON file with an HTTP request, parses the response with .json() and then passes it to oidcSecurityService.setupModule().
I use eval() on the .storage property, because it is stored as a string in JSON and needs to refer to a variable in the code.

When passing "sessionStorage" or "localStorage" from JSON to openIDImplicitFlowConfiguration.storage, the console throws the following error after calling authorize() and successfully logging in with IdentityServer4.

TypeError: Cannot read property 'storage' of undefined
    at AuthConfiguration.get [as storage] (angular-auth-oidc-client.es5.js:230)
    at BrowserStorage.webpackJsonp.../../../../angular-auth-oidc-client/modules/angular-auth-oidc-client.es5.js.BrowserStorage.read (angular-auth-oidc-client.es5.js:298)
    at OidcSecurityCommon.webpackJsonp.../../../../angular-auth-oidc-client/modules/angular-auth-oidc-client.es5.js.OidcSecurityCommon.retrieve (angular-auth-oidc-client.es5.js:350)
    at OidcSecurityService.webpackJsonp.../../../../angular-auth-oidc-client/modules/angular-auth-oidc-client.es5.js.OidcSecurityService.authorizedCallback (angular-auth-oidc-client.es5.js:1173)

It appears as if the storage property can't be read by your library's AuthConfiguration class, even when the openIDImplicitFlowConfiguration.storage is left unassigned (which should revert to DefaultConfiguration's values).

Using:
Node 8.1.4 on Windows 10
NPM 5.2.0
Angular 4.2.6 (& CLI 1.2.1)
angular-auth-oidc-client 1.2.1

Thank you so much for your help, and for your work!
Victor

OidcSecurityService.getToken() only returns authorizationData and not authorizationDataIdToken

Hi Damo,

Im trying out the new angular auth client.

I noticed when using this client ( OidcSecurityService.getToken() )that its not giving me the full access token. Its giving me the authorizationData

baa0badda05ed62ea1b108d7421cf666a00249d5709c4ee50a42b42ce4273162

But it should be giving me the authorizationDataIdToken like:

"eyJhbGciOiJSUzI1NiIsImtpZCI6ImI1ODllOTg0ZmE0ZjZkNDQ0OTIzZDIzNGY2OTIwYmQ5IiwidHlwIjoiSldUIn0.eyJuYmYiOjE1MDA3MTQyMjksImV4cCI6MTUwMDcxNDUyOSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo0NDMwNSIsImF1ZCI6ImFuZ.........."

I looked at the securityService but I only see the getToken function hanging off it.

I am I doing this wrong or is the library wrong?

Cheers

Update Docs with storage configuration

For example, you can get angular-auth-oidc-client to store access tokens in Cookies by downloading and adding Cookie-Storage to your project, creating a factory method to provide it:

let cookieStorageFactory = () => {
return new CookieStorage();
}

..and then adding it to the providers array in @NgModule:
{ provide: Storage, useFactory: cookieStorageFactory }

Large authorizationDataIdToken (because of roles etc.) & cookie storage

Hi

We are pretty new in the Angular and OpenID Connect land, so maybe we are doing things just plain wrong :)

Our IdentityServer (v3 btw) returns a "large" list of claims ("groupSids" and associated roles) from the UserInfoEndpoint

image

The jwt is about >5500 chars.

Now we wanted to implement a proper storage for the auth data, so that we can get the silent renew workflow working, but unfortunately the "authorizationDataIdToken" is too big for the cookie and the browser refuses to save it.

The library tries to load some important oidc-keys (e.g. "exp") from the JWT token so it seems the complete authorizationDataIdToken is needed.

Have you a suggestion for us? Are we using the userinfo endpoint wrong? We also could "split" the jwt in several cookies (like in the old ASP.NET days) and combine them during runtime, but I'm not sure if this is the way we should go.
Or just use the HTML5 localStorage?

We faced a similar problem with our WPF Windows client, but we were using Reference-AccessTokens and using access-tokens & refresh-tokens, but it seems in the Angular world it is different. In the fat client app I only store the accesstoken, the expire-date and the refresh-token and thats it. With them I can get a fresh accesstoken and do a proper logout without the super large JWT token.

Get storage from dependency injection (for server-side rendering)

First of all, I wanted to say thanks for sharing this package. I'm finding it lean, well-conceived, and very useful!

I was trying to use it in the context of a project where I'd like to leverage server-side rendering (SSR) based of this template from @SteveSandersonMS, and I was running into trouble.

One of the constraints of SSR is that there is no access to SessionStorage or LocalStorage. It looks like this package currently depends on these being available in order to successfully retrieve auth tokens from a previous signin.

I'd like to be able to provide server-side mock of the Storage interface that populates its values from cookies. That way, when a page was being rendered in node on the server and it needed to make a call to a protected API, it could pull auth keys from this storage, and everything would work well.

Would you be open to a PR aimed at enabling this scenario? An idea for an approach would be to allow an implementation of Storage to be injected using angular's DI. The constructor of oidc.security.common might look something like this:

constructor(private authConfiguration: AuthConfiguration, private injectedStorage: Storage) {
    if (typeof Storage !== 'undefined') { 
        if (injectedStorage) { this.storage = injectedStorage }
        else { this.storage = sessionStorage; }
    } 
}

Thoughts? I'm happy to work on a PR if you like this direction.

Question: how to get an resource access token?

Context

Given I've got an STS at https://sts.foo.com (based on IdentityServer4)
And an Angular Client at https://client.foo.com
And I want to access an API Resource at https://api.foo.com
When I start an implicit flow
Then I get an ID token 
And I get an Access Token with audience "https://client.foo.com"

Question
How can I request an Access Token with an audience of https://api.foo.com?

Reduce size of package

Package depends on jsrsasign which doesn't tree shake so good. See if it's possible to reduce the size of the auth.module

Question - v1.3.4, anyone seen this?

Have run 1.3.1 / 1.3.2 / 1.3.3 without issue. Went to latest version 1.3.4 and get the error shown in screen dump.

Looking at the code it appears the createAuthorizeUrl is making a call

var /** @type {?} */ customParams =
this.oidcSecurityCommon.retrieve(this.oidcSecurityCommon.storage_custom_request_params);
Object.keys(customParams).forEach(function (key) {
params.set(key, customParams[key]);
});

The 'customParams' object is null hence causing the issue I am seeing locally.

I have tried creating a new app from scratch using the quick start tutorial and still see this problem.

Thoughts?
Thanks!

untitled

Sending credentials to fetch token

Hi,
This might be a question that has a trivial answer, but I'm new to Angular and OIDC.

In order to get a token, where do I specify the Authorization (in header of POST request), and grant_type, username and password (in POST request's body) in the code?

Thanks a lot for your support and for your work!

Silent token renew fails on state validation

I'm having an issue for the silent token renew flow.
After a few (three or four) successful token renewals, it seems that the library is starting two consecutive silent renew sessions, which causes the local state to be overridden and the response from the first renewal attempt fails at the state validation.
I'm also including a console log snippet showing the last successful silent renewal attempt and the following one that failed at the state validation.
Please note that the token provider from my scenario is implemented with Identity Server 4 and I replicated the client configuration from the samples provided at damienbod/AspNet5IdentityServerAngularImplicitFlow for the angularclient client.

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.