Skip to content

Commit 7025090

Browse files
authored
Use Windows SSPI API to generate kerberos ticket for JDBC SSO (#441)
* Use Windows SSPI API to generate Kerberos ticket for JDBC SSO * Use 2 space characters for indentation * Comment out setting sun.security.jgss.lib property, it is not needed anymore * Use set insted of export on Windows * Typo fixes
1 parent 762ba12 commit 7025090

File tree

1 file changed

+136
-0
lines changed

1 file changed

+136
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*
2+
Copyright (c) 2025, Oracle and/or its affiliates.
3+
4+
This software is dual-licensed to you under the Universal Permissive License
5+
(UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License
6+
2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
7+
either license.
8+
9+
Licensed under the Apache License, Version 2.0 (the "License");
10+
you may not use this file except in compliance with the License.
11+
You may obtain a copy of the License at
12+
13+
https://www.apache.org/licenses/LICENSE-2.0
14+
15+
Unless required by applicable law or agreed to in writing, software
16+
distributed under the License is distributed on an "AS IS" BASIS,
17+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18+
See the License for the specific language governing permissions and
19+
limitations under the License.
20+
*/
21+
22+
/*
23+
DESCRIPTION
24+
This sample shows how to use SSO uging Kerberos on Windows.
25+
Since WIN2019 allowtgtsessionkey registry key is not available
26+
and the only option how to acces Kerberos TGT is via Java's SSPI bridge.
27+
28+
PREREQUISITIES
29+
- Configure Kerberos authentication for Oracle database as described here:
30+
https://blog.pythian.com/part-4-implementing-oracle-database-single-sign-on-using-kerberos-active-directory-and-oracle-cmu/
31+
32+
- Create DB user identified extenally as:
33+
CREATE USER <AD LOGIN> IDENTIFIED EXTERNALLY AS '<AD LOGIN>@<AD REALM>';
34+
GRANT CONNECT TO <AD LOGIN>;
35+
36+
- Check your Windows has generater Kerb tickets during logon
37+
klist tgt
38+
klist
39+
40+
- Connect to database using this program.
41+
Java's SSPI bridge(sspi_bridge.dll) should be used to renerate required Kerberos ticket for SSO.
42+
43+
NOTES
44+
Use JDK 13 and above on Windows. Check presence of sspi_bridge.dll in JDK intalation.
45+
46+
MODIFIED (MM/DD/YY)
47+
ibre5041 18/04/2025 - Creation
48+
*/
49+
50+
package kerb;
51+
52+
import java.sql.ResultSet;
53+
import java.sql.Statement;
54+
55+
import java.util.Properties;
56+
57+
import org.ietf.jgss.GSSCredential;
58+
import org.ietf.jgss.GSSManager;
59+
import org.ietf.jgss.GSSName;
60+
import org.ietf.jgss.Oid;
61+
62+
import oracle.jdbc.OracleConnection;
63+
import oracle.jdbc.OracleConnectionBuilder;
64+
import oracle.jdbc.pool.OracleDataSource;
65+
import oracle.net.ano.AnoServices;
66+
67+
public class GSSAuthSSPIConnectSample {
68+
// This should return your AD LOGIN
69+
String username = System.getProperty("user.name");
70+
// This should return your AD KERBEROS REALM
71+
String domain = System.getenv("USERDNSDOMAIN");
72+
// Your Database JDBC URL here
73+
String url = "jdbc:oracle:thin:@//dbhost1:1521/DBSERVICE";
74+
75+
public GSSAuthSSPIConnectSample() {
76+
}
77+
78+
public void doit() throws Exception
79+
{
80+
// Use env variable SSPI_BRIDGE_TRACE=1 in order to trace Java's sspi_bridge.dll plugin
81+
// set SSPI_BRIDGE_TRACE=1
82+
83+
// Various useful tracing options
84+
// System.setProperty("oracle.jdbc.Trace", "true");
85+
// System.setProperty("sun.security.krb5.debug", "true");
86+
// System.setProperty("sun.security.spnego.debug", "true");
87+
// System.setProperty("sun.security.jgss.debug", "true");
88+
// System.setProperty("java.security.debug", "true");
89+
// System.setProperty("sun.security.nativegss.debug", "true");
90+
91+
// Activate SSPI bridge, your Kerberos token will be created using Windows SSPI API
92+
System.setProperty("sun.security.jgss.native", "true");
93+
// Uncomment this this line for JDK 11, for newer JDK versions this value should be default
94+
// System.setProperty("sun.security.jgss.lib", "sspi_bridge.dll");
95+
96+
Oid krb5Oid = new Oid("1.2.840.113554.1.2.2");
97+
GSSManager manager = GSSManager.getInstance();
98+
99+
GSSName srcName = manager.createName(username + "@" + domain, GSSName.NT_USER_NAME);
100+
GSSCredential cred = manager.createCredential(srcName
101+
, GSSCredential.DEFAULT_LIFETIME
102+
, krb5Oid, GSSCredential.INITIATE_ONLY);
103+
104+
Properties prop = new Properties();
105+
prop.setProperty(AnoServices.AUTHENTICATION_PROPERTY_SERVICES, "(" + AnoServices.AUTHENTICATION_KERBEROS5 + ")");
106+
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_SERVICES,"( " + AnoServices.AUTHENTICATION_KERBEROS5 + " )");
107+
prop.setProperty(OracleConnection.CONNECTION_PROPERTY_THIN_NET_AUTHENTICATION_KRB5_MUTUAL, "true");
108+
109+
OracleDataSource ods = new OracleDataSource();
110+
ods.setURL(url);
111+
ods.setConnectionProperties(prop);
112+
OracleConnectionBuilder builder = ods.createConnectionBuilder();
113+
OracleConnection conn = builder.gssCredential(cred).build();
114+
115+
String auth = ((OracleConnection)conn).getAuthenticationAdaptorName();
116+
System.out.println("Authentication adaptor:"+auth);
117+
118+
String sql = "select user from dual";
119+
Statement stmt = conn.createStatement();
120+
ResultSet rs = stmt.executeQuery(sql);
121+
while (rs.next())
122+
System.out.println("whoami: " + rs.getString(1));
123+
124+
conn.close();
125+
}
126+
127+
public static void main(String[] args) {
128+
GSSAuthSSPIConnectSample test = new GSSAuthSSPIConnectSample();
129+
try {
130+
test.doit();
131+
System.out.println("Done");
132+
} catch (Exception e) {
133+
e.printStackTrace();
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)