@@ -4,8 +4,10 @@ package okta
44
55import (
66 "context"
7+ "crypto/rsa"
78 "crypto/tls"
89 "crypto/x509"
10+ "encoding/pem"
911 "fmt"
1012 "net/http"
1113
@@ -19,6 +21,45 @@ import (
1921// these scopes are necessary for group sync functionality.
2022var DefaultScopes = []string {"okta.groups.read" , "okta.users.read" }
2123
24+ // convertToPKCS1 converts a PEM-encoded private key to PKCS#1 format if needed.
25+ // the Okta SDK requires PKCS#1 format (BEGIN RSA PRIVATE KEY), but Okta's
26+ // console generates PKCS#8 keys (BEGIN PRIVATE KEY). this function detects the
27+ // format and converts PKCS#8 to PKCS#1 automatically.
28+ func convertToPKCS1 (keyPEM []byte ) ([]byte , error ) {
29+ block , _ := pem .Decode (keyPEM )
30+ if block == nil {
31+ return nil , errors .New ("failed to decode pem block from private key" )
32+ }
33+
34+ // already in PKCS#1 format
35+ if block .Type == "RSA PRIVATE KEY" {
36+ return keyPEM , nil
37+ }
38+
39+ // convert PKCS#8 to PKCS#1
40+ if block .Type == "PRIVATE KEY" {
41+ key , err := x509 .ParsePKCS8PrivateKey (block .Bytes )
42+ if err != nil {
43+ return nil , errors .Wrap (err , "failed to parse pkcs#8 private key" )
44+ }
45+
46+ rsaKey , ok := key .(* rsa.PrivateKey )
47+ if ! ok {
48+ return nil , errors .New ("private key is not an rsa key" )
49+ }
50+
51+ pkcs1Bytes := x509 .MarshalPKCS1PrivateKey (rsaKey )
52+ pkcs1PEM := pem .EncodeToMemory (& pem.Block {
53+ Type : "RSA PRIVATE KEY" ,
54+ Bytes : pkcs1Bytes ,
55+ })
56+
57+ return pkcs1PEM , nil
58+ }
59+
60+ return nil , errors .Newf ("unsupported private key type: %s" , block .Type )
61+ }
62+
2263// Client wraps the Okta SDK client with custom configuration.
2364type Client struct {
2465 client * okta.Client
@@ -54,11 +95,16 @@ func NewClientWithContext(ctx context.Context, cfg *ClientConfig) (*Client, erro
5495 orgURL = fmt .Sprintf ("https://%s" , cfg .Domain )
5596 }
5697
98+ privateKey , err := convertToPKCS1 (cfg .PrivateKey )
99+ if err != nil {
100+ return nil , errors .Wrap (err , "failed to convert private key" )
101+ }
102+
57103 opts := []okta.ConfigSetter {
58104 okta .WithOrgUrl (orgURL ),
59105 okta .WithAuthorizationMode ("PrivateKey" ),
60106 okta .WithClientId (cfg .ClientID ),
61- okta .WithPrivateKey (string (cfg . PrivateKey )),
107+ okta .WithPrivateKey (string (privateKey )),
62108 }
63109
64110 if len (cfg .Scopes ) > 0 {
0 commit comments