TheThingsStack V3.8.7 with self-signed certificate -> Forbidden Token exchange refused

Hello, everyone,

Unfortunately all older forum entries dealing with this topic are closed, so I have opened a new entry here. I would like to use TheThingsStack V3.8.7 with self-signed certificates. To do so I followed the installation guide. Nevertheless for me it was still necessary to update the docker-compose.yml file because otherwise, for example, after logging into the web console I was not redirect to the console. Instead the url just stayed at console/oauth.

Below are my configuration file:

version: '3.7'
services:
  stack:
    image: 'thethingsnetwork/lorawan-stack:latest' 
    entrypoint: 'ttn-lw-stack -c /config/stack/ttn-lw-stack-docker.yml'
    command: 'start'
   restart: 'unless-stopped'
    volumes:
      - './blob:/srv/ttn-lorawan/public/blob'
      - './config/stack:/stack:ro'
      - './config:/config:ro'        
    environment:      
      TTN_LW_TLS_CERTIFICATE: /config/cert.pem
      TTN_LW_CA: /config/cert.pem
      TTN_LW_TLS_KEY: /config/key.pem
      TTN_LW_CONSOLE_OAUTH_AUTHORIZE_URL: "http://sub.mydomain.com/oauth/authorize"
      TTN_LW_CONSOLE_OAUTH_TOKEN_URL: "http://sub.mydomain.com/oauth/token"
      TTN_LW_IS_OAUTH_UI_CANONICAL_URL: "http://sub.mydomain.com/oauth"
      TTN_LW_BLOB_LOCAL_DIRECTORY: '/srv/ttn-lorawan/public/blob'
      TTN_LW_REDIS_ADDRESS: 'my-dedicated-redis-server:6379'      
      TTN_LW_IS_DATABASE_URI: 'postgres://root@my-dedicated-cockroachdb:26257/ttn_lorawan?sslmode=disable'
      TTN_LW_LOG_LEVEL: debug
    ports:      
      - '80:1885'
      - '443:8885'     
      - '1881:1881'
      - '8881:8881'     
      - '1882:1882'
      - '8882:8882'      
      - '1883:1883'
      - '8883:8883'
      - '1884:1884'
      - '8884:8884'
      - '1887:1887'
      - '1700:1700/udp'

And here the content of my /config/stack/ttn-lw-stack-sdocker.yml:

is:
  email:
    sender-name: 'The Things Stack'
    sender-address: 'noreply@sub.mydomain.com'
    network:
      name: 'The Things Stack'
      console-url: 'https://sub.mydomain.com/console'
      identity-server-url: 'https://sub.mydomain.com/oauth'
  oauth:
    ui:
      canonical-url: 'https://sub.mydomain.com/oauth'
      is:
        base-url: 'https://sub.mydomain.com/api/v3'

http:
  cookie:
    block-key: '' # In the actual file this string is not empty
    hash-key: '' # In the actual file this string is not empty
  metrics:
    password: '' # In the actual file this string is not empty
  pprof:
    password: '' # In the actual file this string is not empty

#tls:
#   source: file
#   root-ca: /run/secrets/cert.pem
#   certificate: /run/secrets/cert.pem
#   key: /run/secrets/key.pem

gs:
  mqtt:
    public-address: 'sub.mydomain.com:1882'
    public-tls-address: 'sub.mydomain.com:8882'
  mqtt-v2:
    public-address: 'sub.mydomain.com:1881'
    public-tls-address: 'sub.mydomain.com:8881'

gcs:
  basic-station:
    default:
      lns-uri: 'wss://sub.mydomain.com:8887'
  the-things-gateway:
    default:
      mqtt-server: 'mqtts://sub.mydomain.com:8881'

console:
  ui:
    canonical-url: 'https://sub.mydomain.com/console'
    is:
      base-url: 'https://sub.mydomain.com/api/v3'
    gs:
      base-url: 'https://sub.mydomain.com/api/v3'
    ns:
      base-url: 'https://sub.mydomain.com/api/v3'
    as:
      base-url: 'https://sub.mydomain.com/api/v3'
    js:
      base-url: 'https://sub.mydomain.com/api/v3'
    qrg:
      base-url: 'https://sub.mydomain.com/api/v3'
    edtc:
      base-url: 'https://sub.mydomain.com/api/v3'

  oauth:
    authorize-url: 'https://sub.mydomain.com/oauth/authorize'
    logout-url: 'https://sub.mydomain.com/oauth/logout'
    token-url: 'https://sub.mydomain.com/oauth/token'
    client-id: '' # In the actual file this string is not empty
    client-secret: '' In the actual file this string is not empy

Here is the log that comes after I log into the console:

stack_1  |  DEBUG Run database query                       duration=4ms namespace=identityserver query=SELECT users.id, users.created_at, users.updated_at, password FROM "users" LEFT JOIN accounts ON accounts.account_type = $1 AND accounts.account_id = users.id WHERE "users"."deleted_at" IS NULL AND ((accounts.uid = $2)) ORDER BY "users"."id" ASC LIMIT 1 rows=1 source=user_store.go:121 values=[user christophmerscher]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT * FROM "accounts"  WHERE "accounts"."deleted_at" IS NULL AND (("account_id" IN ($1) AND "account_type" = $2)) ORDER BY "accounts"."id" ASC rows=1 source=user_store.go:121 values=[4af2f2d7-7ed7-4a62-9dd0-4a555ea5fc60 user]
stack_1  |  DEBUG Run database query                       duration=3ms namespace=identityserver query=SELECT users.id FROM "users" LEFT JOIN accounts ON accounts.account_type = $1 AND accounts.account_id = users.id WHERE "users"."deleted_at" IS NULL AND ((accounts.uid = $2)) ORDER BY "users"."id" ASC LIMIT 1 rows=1 source=store.go:59 values=[user christophmerscher]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=INSERT INTO "user_sessions" ("created_at","updated_at","user_id","expires_at") VALUES ($1,$2,$3,$4) RETURNING "user_sessions"."id" rows=1 source=store.go:72 values=[2020-07-31 08:12:46.533 +0000 UTC 2020-07-31 08:12:46.533 +0000 UTC 4af2f2d7-7ed7-4a62-9dd0-4a555ea5fc60 <nil>]
stack_1  |   INFO Request handled                          duration=41.40977ms method=POST namespace=web remote_addr=128.141.150.246 request_id=01EEHYWFH0CC4B546YW2AV9V8B response_size=0 status=204 url=http://sub.mydomain.com/oauth/api/auth/login
stack_1  |  DEBUG Run database query                       duration=3ms namespace=identityserver query=SELECT users.id FROM "users" LEFT JOIN accounts ON accounts.account_type = $1 AND accounts.account_id = users.id WHERE "users"."deleted_at" IS NULL AND ((accounts.uid = $2)) ORDER BY "users"."id" ASC LIMIT 1 rows=1 source=store.go:59 values=[user christophmerscher]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT * FROM "user_sessions"  WHERE ("user_sessions"."id" = $1) AND ("user_sessions"."user_id" = $2) rows=1 source=user_session_store.go:88 values=[e9e06a41-6a71-48aa-82d8-e751d6376eea 4af2f2d7-7ed7-4a62-9dd0-4a555ea5fc60]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT * FROM "clients"  WHERE "clients"."deleted_at" IS NULL AND ((client_id = $1)) ORDER BY "clients"."id" ASC LIMIT 1 rows=1 source=client_store.go:113 values=[console]
stack_1  |  DEBUG Run database query                       duration=1ms namespace=identityserver query=SELECT * FROM "attributes"  WHERE ("entity_id" IN ($1) AND "entity_type" = $2) ORDER BY "attributes"."id" ASC rows=0 source=client_store.go:113 values=[7c147cb8-6ce7-443f-8e14-298e1fffc806 client]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT clients.id FROM "clients"  WHERE "clients"."deleted_at" IS NULL AND ((client_id = $1)) ORDER BY "clients"."id" ASC LIMIT 1 rows=1 source=store.go:59 values=[console]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT users.id FROM "users" LEFT JOIN accounts ON accounts.account_type = $1 AND accounts.account_id = users.id WHERE "users"."deleted_at" IS NULL AND ((accounts.uid = $2)) ORDER BY "users"."id" ASC LIMIT 1 rows=1 source=store.go:59 values=[user christophmerscher]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT * FROM "client_authorizations"  WHERE ("client_authorizations"."client_id" = $1) AND ("client_authorizations"."user_id" = $2) ORDER BY "client_authorizations"."id" ASC LIMIT 1 rows=1 source=oauth_store.go:104 values=[7c147cb8-6ce7-443f-8e14-298e1fffc806 4af2f2d7-7ed7-4a62-9dd0-4a555ea5fc60]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=UPDATE "client_authorizations" SET "created_at" = $1, "updated_at" = $2, "client_id" = $3, "user_id" = $4, "rights" = $5  WHERE "client_authorizations"."id" = $6 rows=1 source=oauth_store.go:116 values=[2020-07-30 11:01:36.034 +0000 UTC 2020-07-31 08:12:46.564 +0000 UTC 7c147cb8-6ce7-443f-8e14-298e1fffc806 4af2f2d7-7ed7-4a62-9dd0-4a555ea5fc60 {[RIGHT_ALL] {} 0} 77d48799-7cfb-4e30-9c47-674b3749f0e3]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT clients.id FROM "clients"  WHERE "clients"."deleted_at" IS NULL AND ((client_id = $1)) ORDER BY "clients"."id" ASC LIMIT 1 rows=1 source=store.go:59 values=[console]
stack_1  |  DEBUG Run database query                       duration=2ms namespace=identityserver query=SELECT users.id FROM "users" LEFT JOIN accounts ON accounts.account_type = $1 AND accounts.account_id = users.id WHERE "users"."deleted_at" IS NULL AND ((accounts.uid = $2)) ORDER BY "users"."id" ASC LIMIT 1 rows=1 source=store.go:59 values=[user christophmerscher]
stack_1  |  DEBUG Run database query                       duration=1ms namespace=identityserver query=INSERT INTO "authorization_codes" ("created_at","updated_at","client_id","user_id","user_session_id","rights","code","redirect_uri","state","expires_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) RETURNING "authorization_codes"."id" rows=1 source=store.go:72 values=[2020-07-31 08:12:46.558 +0000 UTC 2020-07-31 08:12:46.573 +0000 UTC 7c147cb8-6ce7-443f-8e14-298e1fffc806 4af2f2d7-7ed7-4a62-9dd0-4a555ea5fc60 0xc00030e6a8 {[RIGHT_ALL] {} 0} MF2XI.AJO7SWWNJVCTU57EASTJBJNE7FAXKLRTB3XVBJA.YU7CTA7QY3KNY6UPKTWF5E545453MIZZILRJHK4WGBXPEP6OVFEQ https://sub.mydomain.com/console/oauth/callback GVuTmwbLcCbU7K-v 2020-07-31 08:17:46.558817984 +0000 UTC]
stack_1  |   INFO Request handled                          duration=26.231695ms method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWFJPP14BHM6V3HR0358D response_size=0 status=302 url=http://sub.mydomain.com/oauth/authorize?client_id=console&redirect_uri=https%3A%2F%2Fsub.mydomain.com%2Fconsole%2Foauth%2Fcallback&response_type=code&state=GVuTmwbLcCbU7K-v
stack_1  |   INFO Client error                             duration=1.004904987s method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWFM3CG5B8W6FD1DK3N49 response_size=940 status=403 url=https://sub.mydomain.com/console/oauth/callback?code=MF2XI.AJO7SWWNJVCTU57EASTJBJNE7FAXKLRTB3XVBJA.YU7CTA7QY3KNY6UPKTWF5E545453MIZZILRJHK4WGBXPEP6OVFEQ&state=GVuTmwbLcCbU7K-v
stack_1  |   INFO Request handled                          duration=5.058578ms method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWGMSHP8BBMDBK29BEEXE response_size=273513 status=200 url=https://sub.mydomain.com/assets/console.c6ddc5f8af3f8c39f150.css
stack_1  |   INFO Request handled                          duration=35.401639ms method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWGMS6VQAWMCKQT836SK1 response_size=3844883 status=200 url=https://sub.mydomain.com/assets/console.df2eb219cc37cf35b89a.js
stack_1  |   INFO Client error                             duration=570.165µs method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWH4H70VJXT06P6KBBDCR response_size=198 status=401 url=https://sub.mydomain.com/console/api/auth/token
stack_1  |   INFO Request handled                          duration=506.619µs method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWH4SERGY7QCZGN7ADKWP response_size=35390 status=200 url=https://sub.mydomain.com/assets/console-touch-icon.png
stack_1  |   INFO Request handled                          duration=318.424µs method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWH4SVWCBQ750R2S7F6CV response_size=6239 status=200 url=https://sub.mydomain.com/assets/console-favicon.svg
stack_1  |   INFO Request handled                          duration=300.513µs method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWH575J9ANF2JMW5CJ4KH response_size=5004 status=200 url=https://sub.mydomain.com/assets/logo.svg
stack_1  |   INFO Request handled                          duration=3.859516ms method=GET namespace=web remote_addr=128.141.150.246 request_id=01EEHYWH5M92MBB176Z8PD3360 response_size=699912 status=200 url=https://sub.mydomain.com/assets/ttn-console-bg.498252edc489187693a4e32162260925.png

Please not that in my actual file instead of sub.mydomain.com I use a domain that belongs to me.

I already read a post entry with a simillar problem but this did not do the trick for me. Also I checked this github issue where it is mentioned that it have been solved. However, this is not the case for me.

Any ideas ?

No one ?

Okay in case anyone facing the same issue. For me it was that when I was being redirected to the console it looked for the certificates in a different place. Copying the certificates to this place solved the issue.

1 Like