Dette er en klient som kobler seg opp til Maskinporten (https://difi.github.io/idporten-oidc-dokumentasjon/oidc_auth_server-to-server-oauth2.html) og ber om en JWT-access-token basert på et virksomhetssertifikat, en issuer (konto hos Difi) og ett eller flere scopes.
Husk å be Difi konfigurere opp klienten til å sende JWT-access-token og ikke "token by reference".
Mottatte access-token blir lagret i en cache og vil bli gjenbrukt frem til de utløper. Det er mulig å fjerne access-tokenet fra cachen før det utløper og blir ugyldig. Dette er nyttig dersom det gjøres en forespørsel rett før tokenet utløper og det er fare for at tokenet blir ugyldig før forespørselen sendes. Konfigurasjon gjøres ved initiering av klienten og styres i feltet "numberOfSecondsLeftBeforeExpire".
Digdir vedlikeholder liste med gyldige verdier for miljøene de tilbyr
Versjon | Java baseline | Spring Boot versjon | Status |
---|---|---|---|
3.x | Java 17 | 3.X | Aktiv |
2.X | Java 11 | 2.X | Vedlikehold |
- Aktiv: versjon som aktivt utvikles og holdes oppdatert mht. avhengigheter
- Vedlikehold: kun kritiske feil vil bli adressert
<dependency>
<groupId>no.ks.fiks</groupId>
<artifactId>maskinporten-client</artifactId>
<version>x.x.x</version>
</dependency>
import no.ks.fiks.maskinporten.Maskinportenklient;
import no.ks.fiks.maskinporten.MaskinportenklientProperties;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class Application {
public static void main(String[] args) throws Exception {
String keyStoreFilename = "virksomhetssertifikat-auth.p12";
String alias = "authentication certificate";
char[] keyStorePassword = "passord".toCharArray();
KeyStore keyStore = getKeyStore(keyStoreFilename, keyStorePassword);
Maskinportenklient maskinporten = Maskinportenklient.builder()
.withPrivateKey((PrivateKey) keyStore.getKey(alias, keyStorePassword))
.withProperties(
MaskinportenklientProperties.builder()
.numberOfSecondsLeftBeforeExpire(10)
.issuer("<klient-id-utdelt-av-difi>")
.audience("https://test.maskinporten.no/")
.tokenEndpoint("https://test.maskinporten.no/token")
.build()
)
.usingVirksomhetssertifikat((X509Certificate) keyStore.getCertificate(alias))
.build();
String accessToken = maskinporten.getAccessToken("ks:fiks");
System.out.println("accessToken = " + accessToken);
}
private static KeyStore getKeyStore(String keyStoreFilename, char[] keyStorePassword) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(new FileInputStream(keyStoreFilename), keyStorePassword);
return keyStore;
}
}
val keyStore: Keystore = ...
val alias = "mykey"
val password = "keypassword"
val maskinportenklientProperties = MaskinportenklientProperties(
audience = "https://test.maskinporten.no/",
tokenEndpoint = "https://test.maskinporten.no/token",
issuer = "<klient-id-utdelt-av-difi>",
numberOfSecondsLeftBeforeExpire = 10)
val klient = Maskinportenklient(keyStore, "mykey", "keypassword".toCharArray(), maskinportenklientProperties)
val klient = Maskinportenklient.builder()
.withPrivateKey(keyStore.getKey(alias, keyStorePassword) as PrivateKey)
.withProperties(maskinportenklientProperties)
.usingVirksomhetssertifikat(keyStore.getCertificate(alias) as X509Certificate)
.build()
Klienten er basert på Apache HttpClient 5.1.x. Dersom du vil kan du konfigurere denne selv. Da må du selv sørge for å lukke den når klienten ikke skal brukes mer
CloseableHttpClient httpClient = ... //
Maskinportenklient maskinporten = Maskinportenklient.builder()
.withPrivateKey((PrivateKey) keyStore.getKey(alias, keyStorePassword))
.withProperties(
MaskinportenklientProperties.builder()
.audience("https://test.maskinporten.no/")
.tokenEndpoint(tokenEndpoint)
.issuer("77c0a0ba-d20d-424c-b5dd-f1c63da07fc4")
.numberOfSecondsLeftBeforeExpire(10)
.providedHttpClient(httpClient)
.build()
)
.usingVirksomhetssertifikat((X509Certificate) keyStore.getCertificate(alias))
.build();
Maskinporten har støtte for bruk av asymmetriske nøkler i stedet for virksomhetssertifikat, som beskrevet her.
Klient-builderen har støtte for at en slik nøkkel kan konfigureres slik:
Maskinportenklient.builder()
.withPrivateKey(...)
.withProperties(...)
.usingAsymmetricKey("<asymmetrisk nøkkel>")
.build();
Autokonfigurasjon av maskinporten for Spring Boot.
<dependency>
<groupId>no.ks.fiks</groupId>
<artifactId>maskinporten-spring-boot-client</artifactId>
<version>x.x.x</version>
</dependency>
@Bean
public KontaktOgReservasjonsregisteretApi getKontaktOgReservasjonsregisteretApi(Maskinportenklient maskinportenklient) {
return new KontaktOgReservasjonsregisteretApi(maskinportenklient);
}
virksomhetsertifikat.sertifikater:
- sertifikat-type: AUTH
keystore-password: <KEYSTORE_PASSWORD>
keystore-path: <KEYSTORE_PATH>
certificate-alias: <CERTIFICATE_ALIAS>
private-key-alias: <PRIVATE_KEY_ALIAS>
private-key-password: <PRIVATE_KEY_PASSWORD>
maskinporten:
audience: <AUDIENCE>
tokenEndpoint: <TOKEN_ENDPOINT>
issuer: <ISSUER>
numberOfSecondsLeftBeforeExpire: <NUMBER_OF_SECOUNDS>
maskinporten:
audience: <AUDIENCE>
tokenEndpoint: <TOKEN_ENDPOINT>
issuer: <ISSUER>
numberOfSecondsLeftBeforeExpire: <NUMBER_OF_SECOUNDS>
asymmetricKey: <ASYMMETRIC_KEY_ID>
privateKey:
pemFilePath: <URI OR FILE PATH>
I fra versjon 1.0.16 er det også mulig å oppgi "consumerOrg" dersom man skal opptre på vegne av en annen aktør (delegering). Settes i så fall til orgnr til aktør man skal opptre på vegne av. Krever også at oppgitt Maskinporten scope er satt opp til å kreve dette.