Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
benjamin.ertl
aai-identity-harmonization
Commits
ea6b6145
Commit
ea6b6145
authored
Mar 29, 2016
by
benjamin.ertl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
demo
parent
37fd579d
Pipeline
#1185
skipped
Changes
21
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
341 additions
and
1243 deletions
+341
-1243
link.scim
link.scim
+23
-0
pom.xml
pom.xml
+0
-29
src/main/java/edu/kit/scc/AuthenticationController.java
src/main/java/edu/kit/scc/AuthenticationController.java
+7
-272
src/main/java/edu/kit/scc/EncryptedAssertion.java
src/main/java/edu/kit/scc/EncryptedAssertion.java
+0
-64
src/main/java/edu/kit/scc/EncryptedAssertionRepository.java
src/main/java/edu/kit/scc/EncryptedAssertionRepository.java
+0
-10
src/main/java/edu/kit/scc/IdentityHarmonizer.java
src/main/java/edu/kit/scc/IdentityHarmonizer.java
+130
-77
src/main/java/edu/kit/scc/RestServiceController.java
src/main/java/edu/kit/scc/RestServiceController.java
+37
-7
src/main/java/edu/kit/scc/dao/IndigoUserDAO.java
src/main/java/edu/kit/scc/dao/IndigoUserDAO.java
+0
-25
src/main/java/edu/kit/scc/dto/IndigoUser.java
src/main/java/edu/kit/scc/dto/IndigoUser.java
+0
-38
src/main/java/edu/kit/scc/ldap/LdapClient.java
src/main/java/edu/kit/scc/ldap/LdapClient.java
+24
-131
src/main/java/edu/kit/scc/ldap/LdapIndigoUserAttributeMapper.java
.../java/edu/kit/scc/ldap/LdapIndigoUserAttributeMapper.java
+0
-61
src/main/java/edu/kit/scc/ldap/LdapIndigoUserDAO.java
src/main/java/edu/kit/scc/ldap/LdapIndigoUserDAO.java
+0
-149
src/main/java/edu/kit/scc/ldap/LdapPosixGroupDAO.java
src/main/java/edu/kit/scc/ldap/LdapPosixGroupDAO.java
+16
-0
src/main/java/edu/kit/scc/oidc/OidcClient.java
src/main/java/edu/kit/scc/oidc/OidcClient.java
+22
-0
src/main/java/edu/kit/scc/scim/ScimService.java
src/main/java/edu/kit/scc/scim/ScimService.java
+0
-237
src/main/java/edu/kit/scc/scim/ScimUserAttributeMapper.java
src/main/java/edu/kit/scc/scim/ScimUserAttributeMapper.java
+0
-75
src/main/resources/templates/form.html
src/main/resources/templates/form.html
+0
-16
src/main/resources/templates/saml.html
src/main/resources/templates/saml.html
+0
-29
src/test/java/edu/kit/scc/test/ldap/LdapClientTest.java
src/test/java/edu/kit/scc/test/ldap/LdapClientTest.java
+12
-9
unlink.scim
unlink.scim
+70
-0
user.scim
user.scim
+0
-14
No files found.
link.scim
0 → 100644
View file @
ea6b6145
[{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"ka_ym0762",
"externalId":"2abf56d2-9bdc-47d2-a6c7-074c24717879",
"active":true,
"name":{
"formatted":"Arno Nühm",
"familyName":"Nühm",
"givenName":"Arno"
}
},
{
"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
"userName":"umbrella_peter",
"externalId":"2abf56d2-9bdc-8as1-a6c7-074c24769896",
"active":false,
"name":{
"formatted":"Peter Parker",
"familyName":"Parker",
"givenName":"Peter"
}
}
]
pom.xml
View file @
ea6b6145
...
...
@@ -20,7 +20,6 @@
<plugin>
<groupId>
org.apache.maven.plugins
</groupId>
<artifactId>
maven-surefire-plugin
</artifactId>
<version>
2.19.1
</version>
<configuration>
<skipTests>
true
</skipTests>
</configuration>
...
...
@@ -47,30 +46,6 @@
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-thymeleaf
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-data-jpa
</artifactId>
</dependency>
<dependency>
<groupId>
com.h2database
</groupId>
<artifactId>
h2
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-core
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-context
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework
</groupId>
<artifactId>
spring-beans
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.data
</groupId>
<artifactId>
spring-data-commons
</artifactId>
</dependency>
<!-- LDAP -->
<dependency>
...
...
@@ -118,9 +93,5 @@
<artifactId>
jdom
</artifactId>
<version>
2.0.2
</version>
</dependency>
<dependency>
<groupId>
org.hibernate
</groupId>
<artifactId>
hibernate-jpamodelgen
</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
src/main/java/edu/kit/scc/AuthenticationController.java
View file @
ea6b6145
...
...
@@ -8,57 +8,18 @@
*/
package
edu.kit.scc
;
import
java.io.ByteArrayInputStream
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.io.UnsupportedEncodingException
;
import
java.net.URLEncoder
;
import
java.nio.charset.StandardCharsets
;
import
java.nio.file.Files
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.nio.file.StandardOpenOption
;
import
java.security.SecureRandom
;
import
java.security.Security
;
import
java.util.Enumeration
;
import
java.util.Map.Entry
;
import
java.util.zip.DataFormatException
;
import
java.util.zip.DeflaterOutputStream
;
import
java.util.zip.Inflater
;
import
java.util.zip.InflaterInputStream
;
import
javax.crypto.Cipher
;
import
javax.crypto.spec.IvParameterSpec
;
import
javax.crypto.spec.SecretKeySpec
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
javax.ws.rs.FormParam
;
import
javax.xml.bind.DatatypeConverter
;
import
org.apache.commons.codec.binary.Base64
;
import
org.bouncycastle.jce.provider.BouncyCastleProvider
;
import
org.jdom2.Document
;
import
org.jdom2.Element
;
import
org.jdom2.JDOMException
;
import
org.jdom2.filter.ElementFilter
;
import
org.jdom2.input.SAXBuilder
;
import
org.jdom2.output.Format
;
import
org.jdom2.output.XMLOutputter
;
import
org.opensaml.xml.util.XMLHelper
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Controller
;
import
org.springframework.ui.Model
;
import
org.springframework.util.MimeType
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RequestMethod
;
import
org.springframework.web.bind.annotation.RequestParam
;
import
org.springframework.web.servlet.HandlerMapping
;
import
edu.kit.scc.saml.SamlClient
;
@Controller
public
class
AuthenticationController
{
...
...
@@ -74,253 +35,27 @@ public class AuthenticationController {
@Value
(
"${oauth2.clientId}"
)
private
String
oauth2ClientId
;
@Autowired
SamlClient
samlClient
;
@Autowired
EncryptedAssertionRepository
repository
;
@RequestMapping
(
path
=
"/assertions/**"
)
// , produces =
// "application/octet-stream")
public
void
getAssertion
(
HttpServletRequest
request
,
HttpServletResponse
response
)
{
String
path
=
(
String
)
request
.
getAttribute
(
HandlerMapping
.
PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
);
log
.
debug
(
path
);
path
=
path
.
replace
(
"/assertions/"
,
""
);
log
.
debug
(
path
);
Path
p
=
Paths
.
get
(
"assertions"
,
path
);
try
{
byte
[]
content
=
Files
.
readAllBytes
(
p
);
response
.
setContentLength
(
content
.
length
);
OutputStream
outStream
=
response
.
getOutputStream
();
outStream
.
write
(
content
);
outStream
.
close
();
}
catch
(
Exception
e
)
{
log
.
error
(
"ERROR {}"
,
e
.
getMessage
());
e
.
printStackTrace
();
}
}
@RequestMapping
(
path
=
"/SAML2/POST"
,
method
=
RequestMethod
.
POST
)
public
String
saml
(
@RequestParam
(
"SAMLResponse"
)
String
samlResponse
,
HttpServletRequest
request
,
Model
model
)
{
String
path
=
(
String
)
request
.
getAttribute
(
HandlerMapping
.
PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
);
log
.
debug
(
path
);
// for (Enumeration<String> e = request.getAttributeNames();
// e.hasMoreElements();) {
// String attribute = e.nextElement();
// log.debug("{} {}", attribute, request.getAttribute(attribute));
// }
for
(
Entry
entry
:
request
.
getParameterMap
().
entrySet
())
log
.
debug
(
"{} {}"
,
entry
.
getKey
(),
entry
.
getValue
());
String
decodedAuthnRequestXML
=
""
;
try
{
Base64
base64Decoder
=
new
Base64
();
byte
[]
xmlBytes
=
samlResponse
.
getBytes
(
"UTF-8"
);
byte
[]
base64DecodedByteArray
=
base64Decoder
.
decode
(
xmlBytes
);
try
{
Inflater
inflater
=
new
Inflater
(
true
);
inflater
.
setInput
(
base64DecodedByteArray
);
byte
[]
xmlMessageBytes
=
new
byte
[
5000
];
int
resultLength
=
inflater
.
inflate
(
xmlMessageBytes
);
if
(!
inflater
.
finished
())
{
throw
new
RuntimeException
(
"didn't allocate enough space to hold "
+
"decompressed data"
);
}
inflater
.
end
();
decodedAuthnRequestXML
=
new
String
(
xmlMessageBytes
,
0
,
resultLength
,
"UTF-8"
);
}
catch
(
DataFormatException
e
)
{
log
.
warn
(
"WARNING {}"
,
e
.
getMessage
());
ByteArrayInputStream
bais
=
new
ByteArrayInputStream
(
base64DecodedByteArray
);
ByteArrayOutputStream
baos
=
new
ByteArrayOutputStream
();
InflaterInputStream
iis
=
new
InflaterInputStream
(
bais
);
byte
[]
buf
=
new
byte
[
1024
];
int
count
=
iis
.
read
(
buf
);
while
(
count
!=
-
1
)
{
baos
.
write
(
buf
,
0
,
count
);
count
=
iis
.
read
(
buf
);
}
iis
.
close
();
decodedAuthnRequestXML
=
new
String
(
baos
.
toByteArray
());
}
}
catch
(
Exception
e
)
{
log
.
error
(
"ERROR {}"
,
e
.
getMessage
());
// e.printStackTrace();
}
if
(
decodedAuthnRequestXML
.
equals
(
""
))
{
try
{
Base64
base64Decoder
=
new
Base64
();
byte
[]
xmlBytes
=
samlResponse
.
getBytes
(
"UTF-8"
);
byte
[]
base64DecodedByteArray
=
base64Decoder
.
decode
(
xmlBytes
);
decodedAuthnRequestXML
=
new
String
(
base64DecodedByteArray
);
}
catch
(
Exception
e
)
{
log
.
error
(
"ERROR {}"
,
e
.
getMessage
());
e
.
printStackTrace
();
}
}
SAXBuilder
builder
=
new
SAXBuilder
();
String
assertionXMLCompact
=
""
;
try
{
Document
document
=
builder
.
build
(
new
ByteArrayInputStream
(
decodedAuthnRequestXML
.
getBytes
()));
String
[]
samlRequestAttributes
=
new
String
[
4
];
Element
rootElement
=
document
.
getRootElement
();
samlRequestAttributes
[
0
]
=
rootElement
.
getAttributeValue
(
"IssueInstant"
);
samlRequestAttributes
[
1
]
=
rootElement
.
getAttributeValue
(
"ProviderName"
);
samlRequestAttributes
[
2
]
=
rootElement
.
getAttributeValue
(
"AssertionConsumerServiceURL"
);
samlRequestAttributes
[
3
]
=
rootElement
.
getAttributeValue
(
"ID"
);
ElementFilter
filter
=
new
ElementFilter
(
"Assertion"
);
for
(
Element
e
:
rootElement
.
getDescendants
(
filter
))
{
XMLOutputter
outputter
=
new
XMLOutputter
(
Format
.
getPrettyFormat
());
String
assertionXMLPretty
=
outputter
.
outputString
(
e
);
outputter
.
setFormat
(
Format
.
getCompactFormat
());
assertionXMLCompact
=
outputter
.
outputString
(
e
);
model
.
addAttribute
(
"Assertion"
,
assertionXMLPretty
);
model
.
addAttribute
(
"Delegate"
,
assertionXMLCompact
);
}
model
.
addAttribute
(
"IssueInstant"
,
samlRequestAttributes
[
0
]);
model
.
addAttribute
(
"ProviderName"
,
samlRequestAttributes
[
1
]);
model
.
addAttribute
(
"AssertionConsumerServiceURL"
,
samlRequestAttributes
[
2
]);
model
.
addAttribute
(
"ID"
,
samlRequestAttributes
[
3
]);
try
{
Security
.
addProvider
(
new
BouncyCastleProvider
());
byte
[]
byteArray
=
assertionXMLCompact
.
getBytes
();
SecureRandom
secRnd
=
new
SecureRandom
();
char
[]
fileChars
=
new
char
[
8
];
char
[]
VALID_CHARACTERS
=
"abcdefghijklmnopqrstuvwxyz"
.
toCharArray
();
for
(
int
i
=
0
;
i
<
fileChars
.
length
;
i
++)
fileChars
[
i
]
=
VALID_CHARACTERS
[
secRnd
.
nextInt
(
fileChars
.
length
)];
byte
[]
iv
=
new
byte
[
16
];
secRnd
.
nextBytes
(
iv
);
byte
[]
key
=
new
byte
[
16
];
secRnd
.
nextBytes
(
key
);
IvParameterSpec
init_vector
=
new
IvParameterSpec
(
iv
);
SecretKeySpec
secretKey
=
new
SecretKeySpec
(
key
,
"AES"
);
Cipher
c
=
Cipher
.
getInstance
(
"AES/CBC/PKCS7Padding"
);
c
.
init
(
Cipher
.
ENCRYPT_MODE
,
secretKey
,
init_vector
);
byte
[]
encryptedBytes
=
c
.
doFinal
(
byteArray
);
log
.
debug
(
"Init vector {}"
,
DatatypeConverter
.
printHexBinary
(
iv
));
model
.
addAttribute
(
"iv"
,
DatatypeConverter
.
printHexBinary
(
iv
));
log
.
debug
(
"Key {}"
,
DatatypeConverter
.
printHexBinary
(
key
));
model
.
addAttribute
(
"key"
,
DatatypeConverter
.
printHexBinary
(
key
));
byte
[]
returnBytes
=
new
byte
[
encryptedBytes
.
length
+
iv
.
length
];
System
.
arraycopy
(
iv
,
0
,
returnBytes
,
0
,
iv
.
length
);
System
.
arraycopy
(
encryptedBytes
,
0
,
returnBytes
,
iv
.
length
,
encryptedBytes
.
length
);
log
.
debug
(
"Encrypted assertion {}"
,
DatatypeConverter
.
printHexBinary
(
returnBytes
));
model
.
addAttribute
(
"encassertion"
,
DatatypeConverter
.
printHexBinary
(
returnBytes
));
Base64
b64
=
new
Base64
(
true
);
log
.
debug
(
"Encoded assertion {}"
,
new
String
(
b64
.
encode
(
returnBytes
)));
model
.
addAttribute
(
"delegate"
,
new
String
(
b64
.
encode
(
returnBytes
)));
// repository.save(new EncryptedAssertion(key, iv, new
// String(b64.encode(returnBytes))));
Path
p
=
Paths
.
get
(
"assertions"
,
new
String
(
fileChars
));
Files
.
write
(
p
,
new
String
(
b64
.
encode
(
returnBytes
)).
getBytes
(),
StandardOpenOption
.
WRITE
,
StandardOpenOption
.
CREATE_NEW
);
model
.
addAttribute
(
"file"
,
new
String
(
fileChars
));
}
catch
(
Exception
e
)
{
log
.
warn
(
"ERROR {}"
,
e
.
getMessage
());
e
.
printStackTrace
();
}
}
catch
(
Exception
e
)
{
log
.
error
(
"ERROR {}"
,
e
.
getMessage
());
e
.
printStackTrace
();
}
model
.
addAttribute
(
"samlResponse"
,
samlResponse
);
model
.
addAttribute
(
"decodedAuthnRequestXML"
,
decodedAuthnRequestXML
);
return
"saml"
;
}
@RequestMapping
(
"/login"
)
public
String
login
(
HttpServletResponse
response
,
Model
model
)
throws
UnsupportedEncodingException
{
//
String redirectUrl = oauth2AuthorizeUri.replaceAll("/$", "");
//
redirectUrl += "?response_type=code&scope=openid%20email&client_id=";
//
redirectUrl += oauth2ClientId;
//
redirectUrl += "&redirect_uri=";
//
redirectUrl += oauth2RedirectUri;
//
log.debug("Redirect to {}", redirectUrl);
String
redirectUrl
=
oauth2AuthorizeUri
.
replaceAll
(
"/$"
,
""
);
redirectUrl
+=
"?response_type=code&scope=openid%20email&client_id="
;
redirectUrl
+=
oauth2ClientId
;
redirectUrl
+=
"&redirect_uri="
;
redirectUrl
+=
oauth2RedirectUri
;
log
.
debug
(
"Redirect to {}"
,
redirectUrl
);
String
request
=
samlClient
.
getAuthNAssertion
(
"https://192.168.122.99:9443/samlsso"
,
"https://192.168.122.1:8443/SAML2/POST"
,
"sp.scc.kit.edu"
);
try
{
byte
[]
xmlBytes
=
request
.
getBytes
(
StandardCharsets
.
UTF_8
);
log
.
debug
(
"XML request bytes {}"
,
DatatypeConverter
.
printHexBinary
(
xmlBytes
));
// ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
// DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(byteOutputStream);
// deflaterOutputStream.write(xmlBytes, 0, xmlBytes.length);
// deflaterOutputStream.close();
// log.debug("XML deflated request bytes {}",
// DatatypeConverter.printHexBinary(byteOutputStream.toByteArray()));
Base64
base64Encoder
=
new
Base64
();
// byte[] base64EncodedByteArray = base64Encoder.encode(byteOutputStream.toByteArray());
byte
[]
base64EncodedByteArray
=
base64Encoder
.
encode
(
xmlBytes
);
log
.
debug
(
"XML deflated and base64 encoded {}"
,
DatatypeConverter
.
printHexBinary
(
base64EncodedByteArray
));
String
base64EncodedMessage
=
new
String
(
base64EncodedByteArray
);
log
.
debug
(
"XML deflated and base64 encoded {}"
,
base64EncodedMessage
);
String
urlEncodedMessage
=
URLEncoder
.
encode
(
base64EncodedMessage
,
StandardCharsets
.
UTF_8
.
name
());
request
=
urlEncodedMessage
;
SecureRandom
secRnd
=
new
SecureRandom
();
char
[]
VALID_CHARACTERS
=
"abcdefghijklmnopqrstuvwxyz"
.
toCharArray
();
char
[]
chars
=
new
char
[
16
];
for
(
int
i
=
0
;
i
<
chars
.
length
;
i
++)
chars
[
i
]
=
VALID_CHARACTERS
[
secRnd
.
nextInt
(
chars
.
length
)];
model
.
addAttribute
(
"samlrequest"
,
urlEncodedMessage
);
model
.
addAttribute
(
"relaystate"
,
new
String
(
chars
));
log
.
debug
(
"REQUEST {}"
,
urlEncodedMessage
);
}
catch
(
Exception
e
)
{
log
.
error
(
"ERROR {}"
,
e
.
getMessage
());
}
String
redirectUrl
=
"https://192.168.122.99:9443/samlsso?SAMLRequest="
;
model
.
addAttribute
(
"url"
,
"https://192.168.122.99:9443/samlsso"
);
// response.addHeader("Referer", "https://192.168.122.1:8443/");
return
"
form"
;
return
"
redirect:"
+
redirectUrl
;
}
@RequestMapping
(
path
=
"/oauth2"
)
...
...
src/main/java/edu/kit/scc/EncryptedAssertion.java
deleted
100644 → 0
View file @
37fd579d
package
edu.kit.scc
;
import
javax.persistence.Entity
;
import
javax.persistence.GeneratedValue
;
import
javax.persistence.GenerationType
;
import
javax.persistence.Id
;
@Entity
public
class
EncryptedAssertion
{
@Id
@GeneratedValue
(
strategy
=
GenerationType
.
AUTO
)
private
long
id
;
private
byte
[]
key
;
private
byte
[]
iv
;
private
String
base64Assertion
;
protected
EncryptedAssertion
()
{
}
public
EncryptedAssertion
(
byte
[]
key
,
byte
[]
iv
,
String
base64Assertion
)
{
this
.
key
=
key
;
this
.
iv
=
iv
;
this
.
base64Assertion
=
base64Assertion
;
}
public
long
getId
()
{
return
id
;
}
public
void
setId
(
long
id
)
{
this
.
id
=
id
;
}
public
byte
[]
getKey
()
{
return
key
;
}
public
void
setKey
(
byte
[]
key
)
{
this
.
key
=
key
;
}
public
byte
[]
getIv
()
{
return
iv
;
}
public
void
setIv
(
byte
[]
iv
)
{
this
.
iv
=
iv
;
}
public
String
getBase64Assertion
()
{
return
base64Assertion
;
}
public
void
setBase64Assertion
(
String
base64Assertion
)
{
this
.
base64Assertion
=
base64Assertion
;
}
@Override
public
String
toString
()
{
return
String
.
format
(
"Assertion[id=%d, assertion='%s']"
,
id
,
base64Assertion
);
}
}
src/main/java/edu/kit/scc/EncryptedAssertionRepository.java
deleted
100644 → 0
View file @
37fd579d
package
edu.kit.scc
;
import
java.util.List
;
import
org.springframework.data.repository.CrudRepository
;
public
interface
EncryptedAssertionRepository
extends
CrudRepository
<
EncryptedAssertion
,
Long
>
{
List
<
EncryptedAssertion
>
findByBase64Assertion
(
String
base64Assertion
);
}
src/main/java/edu/kit/scc/IdentityHarmonizer.java
View file @
ea6b6145
...
...
@@ -8,26 +8,20 @@
*/
package
edu.kit.scc
;
import
java.
text.ParseException
;
import
java.util.
Arrays
;
import
java.
util.ArrayList
;
import
java.util.
List
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Component
;
import
com.nimbusds.jwt.JWT
;
import
com.nimbusds.jwt.JWTClaimsSet
;
import
com.nimbusds.oauth2.sdk.token.AccessToken
;
import
com.nimbusds.openid.connect.sdk.claims.UserInfo
;
import
com.nimbusds.openid.connect.sdk.token.OIDCTokens
;
import
edu.kit.scc.http.HttpResponse
;
import
edu.kit.scc.oidc.OidcClient
;
import
edu.kit.scc.scim.ScimClient
;
import
edu.kit.scc.scim.ScimListResponse
;
import
edu.kit.scc.dto.PosixGroup
;
import
edu.kit.scc.dto.PosixUser
;
import
edu.kit.scc.ldap.LdapClient
;
import
edu.kit.scc.scim.ScimGroup
;
import
edu.kit.scc.scim.ScimUser
;
import
edu.kit.scc.scim.ScimUser
AttributeMapper
;
import
edu.kit.scc.scim.ScimUser
.Meta
;
@Component
public
class
IdentityHarmonizer
{
...
...
@@ -35,82 +29,141 @@ public class IdentityHarmonizer {
private
static
final
Logger
log
=
LoggerFactory
.
getLogger
(
IdentityHarmonizer
.
class
);
@Autowired
private
Scim
Client
scim
Client
;
private
Ldap
Client
ldap
Client
;
@Autowired
private
OidcClient
oidcClient
;
public
ScimListResponse
harmonizeIdentities
(
String
username
,
OIDCTokens
tokens
)
{
int
identityCount
=
0
;
ScimUser
scimUser
=
scimClient
.
getScimUser
(
username
);
if
(
scimUser
!=
null
)
identityCount
++;
ScimUser
scimUserFromJWT
=
null
;
ScimUserAttributeMapper
mapper
=
new
ScimUserAttributeMapper
();
// OIDC
log
.
debug
(
"Try to get OIDC user information"
);
UserInfo
userInfo
=
null
;
if
(
tokens
!=
null
)
{
try
{
JWT
jwt
=
tokens
.
getIDToken
();
JWTClaimsSet
claimsSet
=
jwt
.
getJWTClaimsSet
();
log
.
debug
(
"Claims set {}"
,
claimsSet
.
toJSONObject
().
toJSONString
());
AccessToken
accessToken
=
tokens
.
getAccessToken
();
userInfo
=
oidcClient
.
requestUserInfo
(
accessToken
.
getValue
(),
claimsSet
);
}
catch
(
ParseException
e
)
{
log
.
error
(
e
.
getMessage
());
public
List
<
ScimUser
>
harmonizeIdentities
(
List
<
ScimUser
>
scimUsers
)
{
ArrayList
<
ScimUser
>
linkedUsers
=
new
ArrayList
<>();
ScimUser
primaryUser
=
null
;
for
(
ScimUser
user
:
scimUsers
)
{
if
(
user
.
isActive
())
{
primaryUser
=
user
;
break
;
}
}
if
(
userInfo
!=
null
)
{
log
.
debug
(
"User info {}"
,
userInfo
.
toJSONObject
().
toJSONString
());
scimUserFromJWT
=
mapper
.
mapFromUserInfo
(
userInfo
);
if
(
scimUserFromJWT
!=
null
)
identityCount
++;
}
if
(
scimUsers
.
remove
(
primaryUser
))
{
PosixUser
primaryPosixUser
=
ldapClient
.
getPosixUser
(
primaryUser
.
getUserName
());
log
.
debug
(
"Primary user {}"
,
primaryPosixUser
.
toString
());
ScimListResponse
scimListResponse
=
new
ScimListResponse
();
scimListResponse
.
setSchemas
(
Arrays
.
asList
(
scimListResponse
.
LIST_RESPONSE_SCHEMA
,
new
ScimUser
().
USER_SCHEMA_2_0
));
scimListResponse
.
setResources
(
Arrays
.
asList
(
scimUser
,
scimUserFromJWT
));
scimListResponse
.
setTotalResults
(
identityCount
);
Meta
metaData
=
new
Meta
();
metaData
.
put
(
"homeDirectory"
,
primaryPosixUser
.
getHomeDirectory
());
metaData
.
put
(
"cn"
,
primaryPosixUser
.
getCommonName
());
metaData
.
put
(
"gidNumber"
,
String
.
valueOf
(
primaryPosixUser
.
getGidNumber
()));
metaData
.
put
(
"uid"
,
primaryPosixUser
.
getUid
());
metaData
.
put
(
"uidNumber"
,
String
.
valueOf
(
primaryPosixUser
.
getUidNumber
()));
log
.
debug
(
"SCIM query response {}"
,
scimListResponse
.
toString
()
);
primaryUser
.
setMeta
(
metaData
);
return
scimListResponse
;
}
List
<
PosixGroup
>
primaryGroups
=
ldapClient
.
getUserGroups
(
primaryUser
.
getUserName
());
log
.
debug
(
"Primary groups {}"
,
primaryGroups
.
toString
());
primaryUser
.
setGroups
(
new
ArrayList
<>());
for
(
ScimUser
secondaryUser
:
scimUsers
)
{
PosixUser
secondaryPosixUser
=
ldapClient
.
getPosixUser
(
secondaryUser
.
getUserName
());
log
.
debug
(
"Secondary user {}"
,
secondaryUser
.
toString
());
metaData
=
new
Meta
();
metaData
.
put
(
"homeDirectory"
,
secondaryPosixUser
.
getHomeDirectory
());
metaData
.
put
(
"cn"
,
secondaryPosixUser
.
getCommonName
());
metaData
.
put
(
"gidNumber"
,
String
.
valueOf
(
secondaryPosixUser
.
getGidNumber
()));
metaData
.
put
(
"uid"
,
secondaryPosixUser
.
getUid
());
metaData
.
put
(
"uidNumber"
,
String
.
valueOf
(
secondaryPosixUser
.
getUidNumber
()));
secondaryUser
.
setMeta
(
metaData
);
List
<
PosixGroup
>
secondaryGroups
=
ldapClient
.
getUserGroups
(
secondaryUser
.
getUserName
());