0

We haven an Angular application that requires authentication. It's done using OpenID Connect with an IdentityServer4 auth server.

Now we want to add additional languages. The language to be used is stored in the user profile we can fetch from our auth server.

Problem: Angular builds one application for each language so I need to know the language before loading the app, but authentication is done during app startup and I don't know the user's language before.

Is there any common approach / best practice how to setup an angular app with multiple languages and Open ID Connect?

I know one option would be to use ngx-translate, but it's deprecated and I'd prefer to stay with the Angular tooling. I also saw, that current angular version support runtime translations but it seems to be still a beta version and not officially released. I'd prefer the "localization during compile time" approach for performance reasons - but I simply cannot find any approach to make this work...

Setup details:

  • Angular 10 behind nginx kubernetes ingress
  • Asp.NET core app with IdentityServer4 as oidc server
Christoph Lütjen
  • 5,403
  • 2
  • 24
  • 33
  • You could create a micro app which will authorize and then redirect to the required app's url. Also, you can redirect directly from your app to the appropriate URL. P.S. I find angular i18n tooling insufficient due to their "static" strategy and inability to have translations within `.ts` file so I prefer using `ngx-translate` – Sergey Jul 29 '20 at 13:26
  • @Sergey - thanks for your comment. Problem with ngx-translate is that it's some kind of deprecated (https://github.com/ngx-translate/core/issues/783). The angular tooling now supports translations in .ts files - the only problem remaining is that it needs the current locale before bootstrap and that said, before OIDC auth client could be created and fetch user claims. – Christoph Lütjen Jul 29 '20 at 14:35
  • I've seen this topic. But nonetheless it still receives updates. Moreover, thanks to Angular team there is not so much breakable changes so I'm sure it will be usable in future during many releases. What's more important - it's opensource, so you can make your copy of this package and continue small updates to make it work for yourself – Sergey Jul 29 '20 at 15:16

3 Answers3

0

Do check out the ASP.NET Core 3.1 IdentityServer4 Identity Bootstrap 4 template with localization project on Github, it supports localization.

Tore Nestenius
  • 16,431
  • 5
  • 30
  • 40
  • Thanks Tore. The tricky thing with Angular is, that there are multiple (one per culture) static web apps and I have to decide somehow which one to load during OpenID Connect implicit auth flow. Do you have a hint for me, which part of this sample can help here? – Christoph Lütjen Jul 22 '20 at 16:25
  • Not really, I think it all depends on your project and need. You could add a country claim in the identity/access-token an try to control the language and what pages to load depending on that. – Tore Nestenius Jul 22 '20 at 18:21
  • Are you happy with my answer or are there something missing? If not, please mark my answer as accepted. – Tore Nestenius Aug 05 '20 at 10:21
  • Thanks again for our answer, but please note that this question focuses on "how to bootstrap angular if language comes from an OIDC server". That's why I cannot mark it as accepted. – Christoph Lütjen Aug 05 '20 at 21:34
0

Do not worry about the details on authentication / OpenID Connect at this moment. Determine what you want to show to a user who has just accessed your app.

  1. If the user accesses your app via a locale-specific URL, you probably want to render your app with the specified locale. This is the trivial case.

  2. If the user does not specify any locale, you have a number of options:

    2.1. Render your app with a default locale.

    2.2. Ask user for a preferred locale.

    2.3. Try to determine user's locale, maybe according to browser's navigator.language, or by user's source IP.

After implementing the above logic to your application, you can add OpenID Connect to your app.

Assuming you are protecting your entire app including Angular with .NET Core, when a user access your app, the user will be forwarded to OpenID Provider for authentication, and then redirected back to your app. Your app will then determine the user's locale according to the strategy you designed in steps 1 and 2 above.

Bill Lam
  • 464
  • 4
  • 6
  • Thanks for your input! Sorry for not being clear about the details. The app will have one single URL. The user's culture is stored in the user profile (.Net core/Identity server). The angular app is a static website (just nginx, no asp.net here). My big problem: I need the culture BEFORE starting the angular app (to chose the right localized build) so I cannot fetch the user profile during angular start (we're already running a localized app). I think this is a quite common setup, so I wonder if there's any "standard" approach / recommended setup? – Christoph Lütjen Jul 26 '20 at 20:10
  • So you need to determine what should be shown to user before user is authenticated. – Bill Lam Jul 27 '20 at 03:17
  • You have two options: 1. Force all anonymous users to authenticate. So you will know the locale of each visitor and avoid the problem. 2. To deal with users who have not logged in, you may use cookie to store/retrieve user's last chosen locale. For first-time visitors who have not got that locale cookie, either 1) ask the user; or 2) show a default locale; or 3) guess user's preferred locale by browser navigator.language or source IP. And save the users' last chosen locale to cookie for their next visit. – Bill Lam Jul 27 '20 at 03:28
  • Thanks Bill. I want to force all users to authenticate, but I still see now way to get the user culture without having to load the app three times: 1. load app => no auth => redirect to oidc server => login => redirect back to app => 2. load app => load user profile an get culture => set cookie (so I can access it in nginx and deliver correct angular build) => 3. reload app, this time with culture from profile/cookie. I can't see a way to prevent this third reload... – Christoph Lütjen Jul 27 '20 at 09:29
  • I see! I think we can agree that the problem is solvable, but it may require performance optimization. The reload between 1 and 2 can be eliminated by [carrying out the authentication in a popup / iframe](https://github.com/damienbod/angular-auth-oidc-client/blob/master/docs/authorizing-popup-iframe.md). The reload between 2 and 3 seems to be [way more difficult to avoid](https://github.com/angular/angular/issues/16477) and I afraid I do not have the expertise to give advice on that area. – Bill Lam Jul 27 '20 at 10:23
  • But the locale-switching reload maybe less of an issue because it only happens for new visitors and users who switched locale recently? – Bill Lam Jul 27 '20 at 10:30
  • I never thought about this iframe approach, sounds interesting and you're right, 3rd reload should happen only for new users. But it's still a little bit dirty and "it feels like" there should be a cleaner option... – Christoph Lütjen Jul 27 '20 at 11:21
  • I think the problem remained is how to dynamically switch locale in Angular. Perhaps you may obtain more feedback by asking a new question in stack overflow? – Bill Lam Jul 28 '20 at 02:00
  • The locale switch is easy because users have to set their locale in their user profile (which is a separate angular app). I think it's simply updating the cookie that stores the locale and reload the app. – Christoph Lütjen Jul 28 '20 at 10:54
0

Instead of having a different build for each locale, can u have one single build, and use Angular i18n to render the page in different language.

The page language can be selected in the below order

  • Use the browser/system default language
  • Use the user's preferred language (this will be available after the login)
  • Use the default language
Newton Joshua
  • 745
  • 1
  • 10
  • 21
  • Thanks @NewtonJoshua but I fear that does not solve the problem: The language is stored in the user profile. To be able to fetch the user profile, we need the user id that we have AFTER authentication (angular oauth oidc lib) = we have if AFTER angular app has started. Even if we use angular runtime localization (NOT ngx-translate) we need the locale id BEFORE the angular app has started. This question is not about selecting the right locale (we know it it's in the profile) - it's about the problem that we need it earlier than we have it. – Christoph Lütjen Aug 01 '20 at 15:39
  • In the app.component, get the navigator.languages and use that language. Once u get the user profile u can switch to that. – Newton Joshua Aug 02 '20 at 07:03
  • Problem here: I would have to reload the app to "switch" the language and that is exactly what I'm trying to avoid. – Christoph Lütjen Aug 03 '20 at 13:53